在jdk8中 -Xms2g不合法,能通過的:-Xms2G
#!/bin/bash JAVA_OPTS="-Xms4G -Xmx4G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./dump-yyy.log -XX:ErrorFile=./jvm-crash.log -Djava.security.egd=file:/dev/./urandom"
#!/bin/bash JAVA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" nohup java -jar $JAVA_OPTS scheduler-0.0.1.jar --spring.profiles.active=dev >/dev/null 2>&1 &
根據上面的配置會在jar文件同級目錄下生成dump-yyy.log文件,在使用Heap分析工具(如mat),需要更改擴展名為hprof,譬如此處,將dump-yyy.log更名為dump-yyy.hprof
nohup java -jar $JAVA_OPTS demo.jar >/dev/null 2>&1 &
Spring-Boot工程啟動參數,spring boot生成的jar,就是一個普通的可執行jar,這個jar的jvm參數需要從java -jar 命令中賦值 設置內存占用最大最小和初始值 要加“m”說明是MB,否則就是KB了. -Xms:初始值 -Xmx:最大值 -Xmn:最小值 java -Xms10m -Xmx80m -jar mod.jar & 時區設置 java -jar -Duser.timezone=GMT+08 mod.jar &
https://gumutianqi1.gitbooks.io/specification-doc/content/specification-doc/spring-boot-guide.html
如何查看上面的配置是否生效:
1.首先查看Tomcat 進程號:
ps -ef | grep tomcat
我們可以看到Tomcat 進程號是 9217
1.查看是否配置生效:
sudo jmap –heap 9217
我們可以看到MaxHeapSize 等參數已經生效。
Attaching to process ID 7740, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.60-b23 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 4294967296 (4096.0MB) NewSize = 1431306240 (1365.0MB) MaxNewSize = 1431306240 (1365.0MB) OldSize = 2863661056 (2731.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 1370488832 (1307.0MB) used = 1272398256 (1213.4535369873047MB) free = 98090576 (93.54646301269531MB) 92.84265776490471% used From Space: capacity = 18350080 (17.5MB) used = 17946064 (17.114700317382812MB) free = 404016 (0.3852996826171875MB) 97.79828752790179% used To Space: capacity = 31981568 (30.5MB) used = 0 (0.0MB) free = 31981568 (30.5MB) 0.0% used PS Old Generation capacity = 2863661056 (2731.0MB) used = 1815913816 (1731.7903671264648MB) free = 1047747240 (999.2096328735352MB) 63.41231662857799% used 28392 interned Strings occupying 3370792 bytes.
http://aoyouzi.iteye.com/blog/2302476
使用actuator:
http://localhost:8080/metrics
{ "mem": 4088122, "mem.free": 3875488, "processors": 4, "instance.uptime": 222308, "uptime": 231631, "systemload.average": 0.02, "heap.committed": 4019712, "heap.init": 4194304, "heap.used": 144223, "heap": 4019712, "nonheap.committed": 70464, "nonheap.init": 2496, "nonheap.used": 68411, "nonheap": 0, "threads.peak": 49, "threads.daemon": 37, "threads.totalStarted": 53, "threads": 45, "classes": 8716, "classes.loaded": 8716, "classes.unloaded": 0, "gc.ps_scavenge.count": 3, "gc.ps_scavenge.time": 86, "gc.ps_marksweep.count": 2, "gc.ps_marksweep.time": 133, "httpsessions.max": -1, "httpsessions.active": 0 }
System metrics
The following system metrics are exposed by Spring Boot:
The total system memory in KB (mem)
The amount of free memory in KB (mem.free)
The number of processors (processors)
The system uptime in milliseconds (uptime)
The application context uptime in milliseconds (instance.uptime)
The average system load (systemload.average)
Heap information in KB (heap, heap.committed, heap.init, heap.used)
Thread information (threads, thread.peak, thread.daemon)
Class load information (classes, classes.loaded, classes.unloaded)
Garbage collection information (gc.xxx.count, gc.xxx.time)
https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html
中文翻譯版:
度量值:
系統信息:包括處理器數量processors、運行時間uptime和instance.uptime、系統平均負載systemload.average。
mem.*:內存概要信息,包括分配給應用的總內存數量以及當前空閑的內存數量。這些信息來自java.lang.Runtime。
heap.*:堆內存使用情況。這些信息來自java.lang.management.MemoryMXBean接口中getHeapMemoryUsage方法獲取的java.lang.management.MemoryUsage。
nonheap.*:非堆內存使用情況。這些信息來自java.lang.management.MemoryMXBean接口中getNonHeapMemoryUsage方法獲取的java.lang.management.MemoryUsage。
threads.*:線程使用情況,包括線程數、守護線程數(daemon)、線程峰值(peak)等,這些數據均來自java.lang.management.ThreadMXBean。
classes.*:應用加載和卸載的類統計。這些數據均來自java.lang.management.ClassLoadingMXBean。
gc.*:垃圾收集器的詳細信息,包括垃圾回收次數gc.ps_scavenge.count、垃圾回收消耗時間gc.ps_scavenge.time、標記-清除算法的次數gc.ps_marksweep.count、標記-清除算法的消耗時間gc.ps_marksweep.time。這些數據均來自java.lang.management.GarbageCollectorMXBean。
httpsessions.*:Tomcat容器的會話使用情況。包括最大會話數httpsessions.max和活躍會話數httpsessions.active。該度量指標信息僅在引入了嵌入式Tomcat作為應用容器的時候才會提供。
gauge.*:HTTP請求的性能指標之一,它主要用來反映一個絕對數值。比如上面示例中的gauge.response.hello: 5,它表示上一次hello請求的延遲時間為5毫秒。
counter.*:HTTP請求的性能指標之一,它主要作為計數器來使用,記錄了增加量和減少量。如上示例中counter.status.200.hello: 11,它代表了hello請求返回200狀態的次數為11。
對於gauge.*和counter.*的統計,這里有一個特殊的內容請求star-star,它代表了對靜態資源的訪問。這兩類度量指標非常有用,我們不僅可以使用它默認的統計指標,還可以在程序中輕松的增加自定義統計值。只需要通過注入org.springframework.boot.actuate.metrics.CounterService和org.springframework.boot.actuate.metrics.GaugeService來實現自定義的統計指標信息。
http://blog.csdn.net/hj7jay/article/details/54889659
JVM自定義參數通過java命令的可選項:
-D<name>=<value>
來傳入JVM,傳入的參數作為system的property。因此在程序中可以通過下面的語句獲取參數值:
System.getProperty(<name>)
public class JVMParameter { /** * 運行前設置JVM參數 -Djvm.index=1 * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String jvmIndex = System.getProperty("jvm.index"); System.out.println("jvmIndex=" + jvmIndex); } }
運行class命令:
Java -Djvm.index=1 JVMParameter
說明:
JVM自定義參數可用來在集群環境區分當前class運行在哪個JVM上,可以達到讓某個class只在某個指定的JVM上運行,避免多個JVM同時運行,出現混亂。
C:\>java -help 用法: java [-options] class [args...] (執行類) 或 java [-options] -jar jarfile [args...] (執行 jar 文件) 其中選項包括: -d32 使用 32 位數據模型 (如果可用) -d64 使用 64 位數據模型 (如果可用) -server 選擇 "server" VM 默認 VM 是 server. -cp <目錄和 zip/jar 文件的類搜索路徑> -classpath <目錄和 zip/jar 文件的類搜索路徑> 用 ; 分隔的目錄, JAR 檔案 和 ZIP 檔案列表, 用於搜索類文件。 -D<名稱>=<值> 設置系統屬性 -verbose:[class|gc|jni] 啟用詳細輸出 -version 輸出產品版本並退出
java啟動參數共分為三類;
其一是標准參數(-),所有的JVM實現都必須實現這些參數的功能,而且向后兼容;
其二是非標准參數(-X),默認jvm實現這些參數的功能,但是並不保證所有jvm實現都滿足,且不保證向后兼容;
其三是非Stable參數(-XX),此類參數各個jvm實現會有所不同,將來可能會隨時取消,需要慎重使用;
標准參數中比較有用的:
verbose
-verbose:class
輸出jvm載入類的相關信息,當jvm報告說找不到類或者類沖突時可此進行診斷。
-verbose:gc
輸出每次GC的相關情況。
-verbose:jni
輸出native方法調用的相關情況,一般用於診斷jni調用錯誤信息。
非標准參數又稱為擴展參數
一般用到最多的是
-Xms512m 設置JVM促使內存為512m。此值可以設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。
-Xmx512m ,設置JVM最大可用內存為512M。
-Xmn200m:設置年輕代大小為200M。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8。
-Xss128k:
設置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應用的線程所需內存大小進行調整。在相同物理內 存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。
-Xloggc:file
與-verbose:gc功能類似,只是將每次GC事件的相關情況記錄到一個文件中,文件的位置最好在本地,以避免網絡的潛在問題。
若與verbose命令同時出現在命令行中,則以-Xloggc為准。
-Xprof
跟蹤正運行的程序,並將跟蹤數據在標准輸出輸出;適合於開發環境調試。
用-XX作為前綴的參數列表在jvm中可能是不健壯的,SUN也不推薦使用,后續可能會在沒有通知的情況下就直接取消了;但是由於這些參數中的確有很多是對我們很有用的,比如我們經常會見到的-XX:PermSize、-XX:MaxPermSize等等;
http://blog.csdn.net/sdujava2011/article/details/50086933
1、堆的大小可以通過 -Xms 和 -Xmx 來設置,一般將他們設置為相同的大小,目的是避免在每次垃圾回收后重新調整堆的大小,比如 -Xms=2g -Xmx=2g 或者 -Xms=512m -Xmx=512m
2、年輕代大小可以通過 -Xmn 來設置,比如-Xmn=2g 或者 -Xmn512m,此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8
3、年老代大小 = 堆大小 – 年輕代大小
4、持久代或者永久代大小可以通過 -XX:PermSize 和 -XX:MaxPermSize 來控制
5、-XX:SurvivorRatio 控制 Eden和Survivor的內存占用比例,默認為8;
如果設置了NewRatio
,那么整個堆空間的1/(NewRatio +1)
就是新生代空間的大小,-XX:NewRatio推薦2到4.
如果同時指定了NewRatio和NewSize,你應該使用更大的那個。於是,當堆空間被創建時,你可以用過下面的表達式計算初始新生代空間的大小:
min(MaxNewSize, max(NewSize, heap/(NewRatio+
1
)))
|
三、JVM內存溢出配置
如何能在JVM遇到OOM錯誤的時候能夠打印heap dump?可以設置-XX:+HeapDumpOnOutOfMemoryError參數,讓JVM在探測到內存OOM的時候打印dump。但是在JVM啟動參數添加這個參數的時候,JVM啟動失敗:Unrecognized VM option '+HeapDumpOnOutOfMemeryError' ,問題的原因是因為沒有添加-XX:HeapDumpPath參數配置。-XX:HeapDumpPath這個參數可以設置dump文件的存放位置。將JVM啟動參數設置成如下格式:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:/
問題得到解決。當JVM發生內存溢出的時候,會在C:/下打印出heap dump
常用參數設置
UseParNewGC表示對新生代采用並行gc;
ParallelGCThreads表示並行的線程數為8,一般是cpu的核個數,當核個數大於8時可能不是很適用;
UseConcMarkSweepGC表示對full gc采用CMS gc;
-XX:+DisableExplicitGC 表示禁止顯式gc,System.gc()
-XX:+UseCMSCompactAtFullCollection 適用於CMS gc,表示在進行gc的同時清理內存碎片,但會加長gc的總時間
-XX:CMSInitiatingOccupancyFraction=80 適用於CMS gc,表示在年老代達到80%使用率時馬上進行回收
在JVM Crash時獲heap信息的一些配置參數:
-XX:ErrorFile=./xxx.log JVM Crash時記錄heap信息
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./yyy.log JVM OOM時記錄heap信息
http://www.cnblogs.com/moonandstar08/p/4924602.html
Trace跟蹤參數
-verbose:gc
-XX:+printGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:log/gc.log // 指定GC log的位置,以文件輸出
-XX:PrintHeapAtGC // 每一次GC后,都打印堆信息
// 類加載信息
-XX:TraceClassLoading
-XX:+PrintClassHistogram
-Ctrl +Break 打印類信息, 類的使用情況
http://www.cnblogs.com/wind90/p/5457235.html
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader loader = HelloWorld. class.getClassLoader();
System.out.println(loader);
//使用ClassLoader.loadClass()來加載類,不會執行初始化塊
loader.loadClass( "Test2");
//使用Class.forName()來加載類,默認會執行初始化塊
// Class.forName("Test2");
//使用Class.forName()來加載類,並指定ClassLoader,初始化時不執行靜態塊
// Class.forName("Test2", false, loader);
}
}
static {
System.out.println( "靜態初始化塊執行了!");
}
}
http://lavasoft.blog.51cto.com/62575/184547/
java一般使用兩個path:classpath 和 java.library.path
classpath是指向jar包的位置
java.library.path是非java類包的位置如(dll,so)
解決辦法:1:LINUX下的系統變量LD_LIBRARY_PATH來添加java.library.path
2:在vm arguments里添加-Djava.library.path= /usr/local/lib
3:見下圖
開發、應用中老是會遇到OutOfMemory異常,而且常常是過一段時間內存才被吃光,這里可以利用java heap dump出jvm內存鏡像,然后再對其進行分析來查找問題。
http://www.cnblogs.com/linhaohong/archive/2012/07/12/2588660.html
如果嫌配置-classpath麻煩,可以用-Djava.ext.dir 參數替代,這樣就可以批量引入jar包.
但是有個問題需要注意,java默認用的ext目錄是$JAVA_HOME/jre/lib/ext,所以如果你指定了-Djava.ext.dir 參數,則原$JAVA_HOME/jre/lib/ext下的jar包將不會被引用,可能會導致你的程序出現問題;
例如有用到SSL協議的地方會出現javax.net.ssl.SSLKeyException: RSA premaster secret error 異常.
最近我在項目中通過jdbc連接sqlserver2008時出現過這樣的問題,就是因為用-Djava.ext.dir 參數替代了-classpath.
解決方法是將$JAVA_HOME/jre/lib/ext下的dnsns.jar,localedata.jar,sunjce_provider.jar,sunpkcs11.jar放置到你指定的java.ext.dir目錄下.
為了防止出現莫名其妙的錯誤,最好整個$JAVA_HOME/jre/lib/ext下的jar包都copy過去.
參考:
http://jony-hwong.iteye.com/blog/315324
http://t8500071.iteye.com/blog/790676
本地部署時拋出異常java.lang.OutOfMemoryError:GC overhead limit exceeded導致服務起不來,查看日志發現加載了太多資源到內存,本地的性能也不好,gc時間消耗的較多。解決這種問題兩種方法是,增加參數,-XX:-UseGCOverheadLimit,關閉這個特性,同時增加heap大小,-Xmx1024m。坑填了,but why?
OOM大家都知道,就是JVM內存溢出了,那GC overhead limit exceed呢?
GC overhead limt exceed檢查是Hotspot VM 1.6定義的一個策略,通過統計GC時間來預測是否要OOM了,提前拋出異常,防止OOM發生。Sun 官方對此的定義是:“並行/並發回收器在GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC並且回收了不到2%的堆內存。用來避免內存過小造成應用不能正常工作。“
聽起來沒啥用...預測OOM有啥用?起初開來這玩意只能用來Catch住釋放內存資源,避免應用掛掉。后來發現一般情況下這個策略不能拯救你的應用,但是可以在應用掛掉之前做最后的掙扎,比如數據保存或者保存現場(Heap Dump)。
而且有些時候這個策略還會帶來問題,比如加載某個大的內存數據時頻繁OOM。
假如你也生產環境中遇到了這個問題,在不知道原因時不要簡單的猜測和規避。可以通過-verbose:gc -XX:+PrintGCDetails看下到底什么原因造成了異常。通常原因都是因為old區占用過多導致頻繁Full GC,最終導致GC overhead limit exceed。如果gc log不夠可以借助於JProfile等工具查看內存的占用,old區是否有內存泄露。分析內存泄露還有一個方法-XX:+HeapDumpOnOutOfMemoryError,這樣OOM時會自動做Heap Dump,可以拿MAT來排查了。還要留意young區,如果有過多短暫對象分配,可能也會拋這個異常。
日志的信息不難理解,就是每次gc時打條日志,記錄GC的類型,前后大小和時間。舉個例子。
33.125: [GC [DefNew: 16000K->16000K(16192K), 0.0000574 secs][Tenured: 2973K->2704K(16384K), 0.1012650 secs] 18973K->2704K(32576K), 0.1015066 secs]
100.667:[Full GC [Tenured: 0K->210K(10240K), 0.0149142 secs] 4603K->210K(19456K), [Perm : 2999K->2999K(21248K)], 0.0150007 secs]
GC和Full GC代表gc的停頓類型,Full GC代表stop-the-world。箭頭兩邊是gc前后的區空間大小,分別是young區、tenured區和perm區,括號里是該區的總大小。冒號前面是gc發生的時間,單位是秒,從jvm啟動開始計算。DefNew代表Serial收集器,為Default New Generation的縮寫,類似的還有PSYoungGen,代表Parallel Scavenge收集器。這樣可以通過分析日志找到導致GC overhead limit exceeded的原因,通過調節相應的參數解決問題。
文中涉及到的名詞解釋,
Eden Space:堆內存池,大多數對象在這里分配內存空間。
Survivor Space:堆內存池,存儲在Eden Space的gc中存活下來的對象。
Tenured Generation:堆內存池,存儲Survivor Space中存活過幾次gc的對象。
Permanent Generation:非堆空間,存儲的是class和method對象。
Code Cache:非堆空間,JVM用來存儲編譯和存儲native code。
最后附上GC overhead limit exceed HotSpot的實現:
bool print_gc_overhead_limit_would_be_exceeded = false; if (is_full_gc) { if (gc_cost() > gc_cost_limit && free_in_old_gen < (size_t) mem_free_old_limit && free_in_eden < (size_t) mem_free_eden_limit) { // Collections, on average, are taking too much time, and // gc_cost() > gc_cost_limit // we have too little space available after a full gc. // total_free_limit < mem_free_limit // where // total_free_limit is the free space available in // both generations // total_mem is the total space available for allocation // in both generations (survivor spaces are not included // just as they are not included in eden_limit). // mem_free_limit is a fraction of total_mem judged to be an // acceptable amount that is still unused. // The heap can ask for the value of this variable when deciding // whether to thrown an OutOfMemory error. // Note that the gc time limit test only works for the collections // of the young gen + tenured gen and not for collections of the // permanent gen. That is because the calculation of the space // freed by the collection is the free space in the young gen + // tenured gen. // At this point the GC overhead limit is being exceeded. inc_gc_overhead_limit_count(); if (UseGCOverheadLimit) { if (gc_overhead_limit_count() >= AdaptiveSizePolicyGCTimeLimitThreshold){ // All conditions have been met for throwing an out-of-memory set_gc_overhead_limit_exceeded(true); // Avoid consecutive OOM due to the gc time limit by resetting // the counter. reset_gc_overhead_limit_count(); } else { // The required consecutive collections which exceed the // GC time limit may or may not have been reached. We // are approaching that condition and so as not to // throw an out-of-memory before all SoftRef's have been // cleared, set _should_clear_all_soft_refs in CollectorPolicy. // The clearing will be done on the next GC. bool near_limit = gc_overhead_limit_near(); if (near_limit) { collector_policy->set_should_clear_all_soft_refs(true); if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr(" Nearing GC overhead limit, " "will be clearing all SoftReference"); } } } } // Set this even when the overhead limit will not // cause an out-of-memory. Diagnostic message indicating // that the overhead limit is being exceeded is sometimes // printed. print_gc_overhead_limit_would_be_exceeded = true; } else { // Did not exceed overhead limits reset_gc_overhead_limit_count(); } }
http://www.cnblogs.com/hucn/p/3572384.html