一次apk打開時報記憶體溢出錯誤,故寫下記憶體溢出的各種原因和解決方法

来源:https://www.cnblogs.com/LambertL/archive/2019/03/05/10476278.html
-Advertisement-
Play Games

原轉載:https://blog.csdn.net/cp_panda_5/article/details/79613870 正文內容: 對於JVM的記憶體寫過的文章已經有點多了,而且有點爛了,不過說那麼多大多數在解決OOM的情況,於此,本文就只闡述這個內容,攜帶一些分析和理解和部分擴展內容,也就是JV ...


原轉載:https://blog.csdn.net/cp_panda_5/article/details/79613870

 

正文內容:

對於JVM的記憶體寫過的文章已經有點多了,而且有點爛了,不過說那麼多大多數在解決OOM的情況,於此,本文就只闡述這個內容,攜帶一些分析和理解和部分擴展內容,也就是JVM宕機中的一些問題,OK,下麵說下OOM的常見情況:

 

第一類記憶體溢出,也是大家認為最多,第一反應認為是的記憶體溢出,就是堆棧溢出:

那什麼樣的情況就是堆棧溢出呢?當你看到下麵的關鍵字的時候它就是堆棧溢出了:

java.lang.OutOfMemoryError: ......java heap space.....

也就是當你看到heap相關的時候就肯定是堆棧溢出了,此時如果代碼沒有問題的情況下,適當調整-Xmx和-Xms是可以避免的,不過一定是代碼沒有問題的前提,為什麼會溢出呢,要麼代碼有問題,要麼訪問量太多並且每個訪問的時間太長或者數據太多,導致數據釋放不掉,因為垃圾回收器是要找到那些是垃圾才能回收,這裡它不會認為這些東西是垃圾,自然不會去回收了;主意這個溢出之前,可能系統會提前先報錯關鍵字為:

java.lang.OutOfMemoryError:GC over head limit exceeded

這種情況是當系統處於高頻的GC狀態,而且回收的效果依然不佳的情況,就會開始報這個錯誤,這種情況一般是產生了很多不可以被釋放的對象,有可能是引用使用不當導致,或申請大對象導致,但是java heap space的記憶體溢出有可能提前不會報這個錯誤,也就是可能記憶體就直接不夠導致,而不是高頻GC.

 

第二類記憶體溢出,PermGen的溢出,或者PermGen 滿了的提示,你會看到這樣的關鍵字:

關鍵信息為:

java.lang.OutOfMemoryError: PermGen space

原因:系統的代碼非常多或引用的第三方包非常多、或代碼中使用了大量的常量、或通過intern註入常量、或者通過動態代碼載入等方法,導致常量池的膨脹,雖然JDK 1.5以後可以通過設置對永久帶進行回收,但是我們希望的是這個地方是不做GC的,它夠用就行,所以一般情況下今年少做類似的操作,所以在面對這種情況常用的手段是:增加-XX:PermSize和-XX:MaxPermSize的大小。

 

第三類記憶體溢出:在使用ByteBuffer中的allocateDirect()的時候會用到,很多javaNIO的框架中被封裝為其他的方法

溢出關鍵字:

java.lang.OutOfMemoryError: Direct buffer memory
如果你在直接或間接使用了ByteBuffer中的allocateDirect方法的時候,而不做clear的時候就會出現類似的問題,常規的引用程式IO輸出存在一個內核態與用戶態的轉換過程,也就是對應直接記憶體與非直接記憶體,如果常規的應用程式你要將一個文件的內容輸出到客戶端需要通過OS的直接記憶體轉換拷貝到程式的非直接記憶體(也就是heap中),然後再輸出到直接記憶體由操作系統發送出去,而直接記憶體就是由OS和應用程式共同管理的,而非直接記憶體可以直接由應用程式自己控制的記憶體,jvm垃圾回收不會回收掉直接記憶體這部分的記憶體,所以要註意了哦。

如果經常有類似的操作,可以考慮設置參數:-XX:MaxDirectMemorySize

 

第四類記憶體溢出錯誤:

溢出關鍵字:

java.lang.StackOverflowError

這個參數直接說明一個內容,就是-Xss太小了,我們申請很多局部調用的棧針等內容是存放在用戶當前所持有的線程中的,線程在jdk 1.4以前預設是256K,1.5以後是1M,如果報這個錯,只能說明-Xss設置得太小,當然有些廠商的JVM不是這個參數,本文僅僅針對Hotspot VM而已;不過在有必要的情況下可以對系統做一些優化,使得-Xss的值是可用的。

 

第五類記憶體溢出錯誤:

溢出關鍵字:

java.lang.OutOfMemoryError: unable to create new native thread

上面第四種溢出錯誤,已經說明瞭線程的記憶體空間,其實線程基本只占用heap以外的記憶體區域,也就是這個錯誤說明除了heap以外的區域,無法為線程分配一塊記憶體區域了,這個要麼是記憶體本身就不夠,要麼heap的空間設置得太大了,導致了剩餘的記憶體已經不多了,而由於線程本身要占用記憶體,所以就不夠用了,說明瞭原因,如何去修改,不用我多說,你懂的。

 

第六類記憶體溢出:

溢出關鍵字

java.lang.OutOfMemoryError: request {} byte for {}out of swap

這類錯誤一般是由於地址空間不夠而導致。

 

六大類常見溢出已經說明JVM中99%的溢出情況,要逃出這些溢出情況非常困難,除非一些很怪異的故障問題會發生,比如由於物理記憶體的硬體問題,導致了code cache的錯誤(在由byte code轉換為native code的過程中出現,但是概率極低),這種情況記憶體 會被直接crash掉,類似還有swap的頻繁交互在部分系統中會導致系統直接被crash掉,OS地址空間不夠的話,系統根本無法啟動,呵呵;JNI的濫用也會導致一些本地記憶體無法釋放的問題,所以儘量避開JNI;socket連接數據打開過多的socket也會報類似:IOException: Too many open files等錯誤信息。

 

JNI就不用多說了,儘量少用,除非你的代碼太牛B了,我無話可說,呵呵,這種記憶體如果沒有在被調用的語言內部將記憶體釋放掉(如C語言),那麼在進程結束前這些記憶體永遠釋放不掉,解決辦法只有一個就是將進程kill掉。

 

另外GC本身是需要記憶體空間的,因為在運算和中間數據轉換過程中都需要有記憶體,所以你要保證GC的時候有足夠的記憶體哦,如果沒有的話GC的過程將會非常的緩慢。

 

順便這裡就提及一些新的CMS GC的內容和策略(有點亂,每次寫都很亂,但是能看多少看多少吧):

首先我再寫一次一前博客中的已經寫過的內容,就是很多參數沒啥建議值,建議值是自己在現場根據實際情況科學計算和測試得到的綜合效果,建議值沒有絕對好的,而且預設值很多也是有問題的,因為不同的版本和廠商都有很大的區別,預設值沒有永久都是一樣的,就像-Xss參數的變化一樣,要看到你當前的java程式heap的大致情況可以這樣看看(以下參數是隨便設置的,並不是什麼預設值):

$sudo jmap -heap `pgrep java` 
Attaching to process ID 4280, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 19.1-b02

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 134217728 (128.0MB)
MaxNewSize = 134217728 (128.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 268435456 (256.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 85721088 (81.75MB)
used = 22481312 (21.439849853515625MB)
free = 63239776 (60.310150146484375MB)
26.22611602876529% used
From Space:
capacity = 24051712 (22.9375MB)
used = 478488 (0.45632171630859375MB)
free = 23573224 (22.481178283691406MB)
1.9894134770946867% used
To Space:
capacity = 24248320 (23.125MB)
used = 0 (0.0MB)
free = 24248320 (23.125MB)
0.0% used
PS Old Generation
capacity = 939524096 (896.0MB)
used = 16343864 (15.586723327636719MB)
free = 923180232 (880.4132766723633MB)
1.7395896571023124% used
PS Perm Generation
capacity = 134217728 (128.0MB)
used = 48021344 (45.796722412109375MB)
free = 86196384 (82.20327758789062MB)
35.77868938446045% used

 

付:sudo是需要拿到管理員許可權,如果你的系統許可權很大那麼就不需要了,最後的grep java那個內容如果不對,可以直接通過jps或者ps命令將和java相關的進程號直接寫進去,如:java -map 4280,這個參數其實完全可以通過jstat工具來替代,而且看到的效果更加好,這個參數線上上應用中,儘量少用(尤其是高併發的應用中),可能會觸發JVM的bug,導致應用掛起;在jvm 1.6u14後可以編寫任意一段程式,然後在運行程式的時候,增加參數為:-XX:+PrintFlagsFinal來輸出當前JVM中運行時的參數值,或者通過jinfo來查看,jinfo是非常強大的工具,可以對部分參數進行動態修改,當然記憶體相關的東西是不能修改的,只能增加一些不是很相關的參數,有關JVM的工具使用,後續文章中如果有機會我們再來探討,不是本文的重點;補充:關於參數的預設值對不同的JVM版本、不同的廠商、運行於不同的環境(一般和位數有關係)預設值會有區別。

 

OK,再說下反覆的一句,沒有必要的話就不要亂設置參數,參數不是拿來玩的,預設的參數對於這門JDK都是有好處的,關鍵是否適合你的應用場景,一般來講你常規的只需要設置以下幾個參數就可以了:

-server 表示為伺服器端,會提供很多伺服器端預設的配置,如並行回收,而伺服器上一般這個參數都是預設的,所以都是可以省掉,與之對應的還有一個-client參數,一般在64位機器上,JVM是預設啟動-server參數,也就是預設啟動並行GC的,但是是ParallelGC而不是ParallelOldGC,兩者演算法不同(後面會簡單說明下),而比較特殊的是windows 32位上預設是-client,這兩個的區別不僅僅是預設的參數不一樣,在jdk包下的jre包下一般會包含client和server包,下麵分別對應啟動的動態鏈接庫,而真正看到的java、javac等相關命令指示一個啟動導向,它只是根據命令找到對應的JVM並傳入jvm中進行啟動,也就是看到的java.exe這些文件並不是jvm;說了這麼多,最終總結一下就是,-server和-client就是完全不同的兩套VM,一個用於桌面應用,一個用於伺服器的。

-Xmx 為Heap區域的最大值

-Xms 為Heap區域的初始值,線上環境需要與-Xmx設置為一致,否則capacity的值會來回飄動,飄得你心曠神怡,你懂的。

-Xss(或-ss) 這個其實也是可以預設的,如果你真的覺得有設置的必要,你就改下吧,1.5以後是1M的預設大小(指一個線程的native空間),如果代碼不多,可以設置小點來讓系統可以接受更大的記憶體。註意,還有一個參數是-XX:ThreadStackSize,這兩個參數在設置的過程中如果都設置是有衝突的,一般按照JVM常理來說,誰設置在後面,就以誰為主,但是最後發現如果是在1.6以上的版本,-Xss設置在後面的確都是以-Xss為主,但是要是-XX:ThreadStackSize設置在後面,主線程還是為-Xss為主,而其它線程以-XX:ThreadStackSize為主,主線程做了一個特殊判定處理;單獨設置都是以本身為主,-Xss不設置也不會採用其預設值,除非兩個都不設置會採用-Xss的預設值。另外這個參數針對於hotspot的vm,在IBM的jvm中,還有一個參數為-Xoss,主要原因是IBM在對棧的處理上有操作數棧和方法棧等各種不同的棧種類,而hotspot不管是什麼棧都放在一個私有的線程內部的,不區分是什麼棧,所以只需要設置一個參數,而IBM的J9不是這樣的;有關棧上的細節,後續我們有機會專門寫文章來說明。

 

-XX:PermSize與-XX:MaxPermSize兩個包含了class的裝載的位置,或者說是方法區(但不是本地方法區),在Hotspot預設情況下為64M,主意全世界的JVM只有hostpot的VM才有Perm的區域,或者說只有hotspot才有對用戶可以設置的這塊區域,其他的JVM都沒有,其實並不是沒有這塊區域,而是這塊區域沒有讓用戶來設置,其實這塊區域本身也不應該讓用戶來設置,我們也沒有一個明確的說法這塊空間必須要設置多大,都是拍腦袋設置一個數字,如果發佈到線上看下如果用得比較多,就再多點,如果用的少,就減少點,而這塊區域和性能關鍵沒有多大關係,只要能裝下就OK,並且時不時會因為Perm不夠而導致Full GC,所以交給開發者來調節這個參數不知道是怎麼想的;所以Oracle將在新一代JVM中將這個區域徹底刪掉,也就是對用戶透明,G1的如果真正穩定起來,以後JVM的啟動參數將會非常簡單,而且理論上管理再大的記憶體也是沒有問題的,其實G1(garbage first,一種基於region的垃圾收集回收器)已經在hotspot中開始有所試用,不過目前效果不好,還不如CMS呢,所以只是試用,G1已經作為ORACLE對JVM研發的最高重點,CMS自現在最高版本後也不再有新功能(可以修改bug),該項目已經進行5年,尚未發佈正式版,CMS是四五年前發佈的正式版,但是是最近一兩年才開始穩定,而G1的複雜性將會遠遠超越CMS,所以要真正使用上G1還有待考察,全世界目前只有IBM J9真正實現了G1論文中提到的思想(論文於05年左右發表),IBM已經將J9應用於websphere中,但是並不代表這是全世界最好的jvm,全世界最好的jvm是Azul(無停頓垃圾回收演算法和一個零開銷的診斷/監控工具),幾乎可以說這個jvm是沒有暫停的,在全世界很多頂尖級的公司使用,不過價格非常貴,不能直接使用,目前這個jvm的主導者在研究JRockit,而目前hotspot和JRockit都是Oracle的,所以他們可能會合併,所以我們應該對JVM的性能充滿信心。

 

也就是說你常用的情況下只需要設置4個參數就OK了,除非你的應用有些特殊,否則不要亂改,那麼來看看一些其他情況的參數吧:

 

先來看個不大常用的,就是大家都知道JVM新的對象應該說幾乎百分百的在Eden裡面,除非Eden真的裝不下,我們不考慮這種變態的問題,因為線上環境Eden區域都是不小的,來降低GC的次數以及全局 GC的概率;而JVM習慣將記憶體按照較為連續的位置進行分配,這樣使得有足夠的記憶體可以被分配,減少碎片,那麼對於記憶體最後一個位置必然就有大量的徵用問題,JVM在高一點的版本裡面提出了為每個線程分配一些私有的區域來做來解決這個問題,而1.5後的版本還可以動態管理這些區域,那麼如何自己設置和查看這些區域呢,看下英文全稱為:Thread Local Allocation Buffer,簡稱就是:TLAB,即記憶體本地的持有的buffer,設置參數有:

-XX:+UseTLAB 啟用這種機制的意思
-XX:TLABSize=<size in kb> 設置大小,也就是本地線程中的私有區域大小(只有這個區域放不下才會到Eden中去申請)。
-XX:+ResizeTLAB 是否啟動動態修改

這幾個參數在多CPU下非常有用。

-XX:+PrintTLAB 可以輸出TLAB的內容。

 

下麵再閑扯些其它的參數:

 

如果你需要對Yong區域進行並行回收應該如何修改呢?在jdk1.5以後可以使用參數:

-XX:+UseParNewGC

註意: 與它衝突的參數是:-XX:+UseParallelOldGC和-XX:+UseSerialGC,如果需要用這個參數,又想讓整個區域是並行回收的,那麼就使用-XX:+UseConcMarkSweepGC參數來配合,其實這個參數在使用了CMS後,預設就會啟動該參數,也就是這個參數在CMS GC下是無需設置的,後面會提及到這些參數。

 

 

預設伺服器上的對Full並行GC策略為(這個時候Yong空間回收的時候啟動PSYong演算法,也是並行回收的):

-XX:+UseParallelGC

另外,在jdk1.5後出現一個新的參數如下,這個對Yong的回收演算法和上面一樣,對Old區域會有所區別,上面對Old回收的過程中會做一個全局的Compact,也就是全局的壓縮操作,而下麵的演算法是局部壓縮,為什麼要局部壓縮呢?是因為JVM發現每次壓縮後再邏輯上數據都在Old區域的左邊位置,申請的時候從左向右申請,那麼生命力越長的對象就一般是靠左的,所以它認為左邊的對象就是生命力很強,而且較為密集的,所以它針對這種情況進行部分密集,但是這兩種演算法mark階段都是會暫停的,而且存活的對象越多活著的越多;而ParallelOldGC會進行部分壓縮演算法(主意一點,最原始的copy演算法是不需要經過mark階段,因為只需要找到一個或活著的就只需要做拷貝就可以,而Yong區域借用了Copy演算法,只是唯一的區別就是傳統的copy演算法是採用兩個相同大小的記憶體來拷貝,浪費空間為50%,所以分代的目標就是想要實現很多優勢所在,認為新生代85%以上的對象都應該是死掉的,所以S0和S1一般並不是很大),該演算法為jdk 1.5以後對於絕大部分應用的最佳選擇。

-XX:+UseParallelOldGC

 

-XX:ParallelGCThread=12:並行回收的線程數,最好根據實際情況而定,因為線程多往往存在徵用調度和上下文切換的開銷;而且也並非CPU越多線程數也可以設置越大,一般設置為12就再增加用處也不大,主要是演算法本身內部的徵用會導致其線程的極限就是這樣。

 

設置Yong區域大小:

-Xmn Yong區域的初始值和最大值一樣大

-XX:NewSize和-XX:MaxNewSize如果設置以為一樣大就是和-Xmn,在JRockit中會動態變化這些參數,根據實際情況有可能會變化出兩個Yong區域,或者沒有Yong區域,有些時候會生出來一個半長命對象區域;這裡除了這幾個參數外,還有一個參數是NewRatio是設置Old/Yong的倍數的,這幾個參數都是有衝突的,伺服器端建議是設置-Xmn就可以了,如果幾個參數全部都有設置,-Xmn和-XX:NewSize與-XX:MaxNewSize將是誰設置在後面,以誰的為準,而-XX:NewSize -XX:MaxNewSize與-XX:NewRatio時,那麼參數設置的結果可能會以下這樣的(jdk 1.4.1後):

min(MaxNewSize,max(NewSize, heap/(NewRatio+1)))

-XX:NewRatio為Old區域為Yong的多少倍,間接設置Yong的大小,1.6中如果使用此參數,則預設會在適當時候被動態調整,具體請看下麵參數UseAdaptiveSizepollcy 的說明。

三個參數不要同時設置,因為都是設置Yong的大小的。

 

-XX:SurvivorRatio:該參數為Eden與兩個求助空間之一的比例,註意Yong的大小等價於Eden + S0 + S1,S0和S1的大小是等價的,這個參數為Eden與其中一個S區域的大小比例,如參數為8,那麼Eden就占用Yong的80%,而S0和S1分別占用10%。

以前的老版本有一個參數為:-XX:InitialSurivivorRatio,如果不做任何設置,就會以這個參數為準,這個參數的預設值就是8,不過這個參數並不是Eden/Survivor的大小,而是Yong/Survivor,所以所以預設值8,代表每一個S區域的空間大小為Yong區域的12.5%而不是10%。另外順便提及一下,每次大家看到GC日誌的時候,GC日誌中的每個區域的最大值,其中Yong的空間最大值,始終比設置的Yong空間的大小要小一點,大概是小12.5%左右,那是因為每次可用空間為Eden加上一個Survivor區域的大小,而不是整個Yong的大小,因為可用空間每次最多是這樣大,兩個Survivor區域始終有一塊是空的,所以不會加上兩個來計算。

 

-XX:MaxTenuringThreshold=15:在正常情況下,新申請的對象在Yong區域發生多少次GC後就會被移動到Old(非正常就是S0或S1放不下或者不太可能出現的Eden都放不下的對象),這個參數一般不會超過16(因為計數器從0開始計數,所以設置為15的時候相當於生命周期為16)。

要查看現在的這個值的具體情況,可以使用參數:-XX:+PrintTenuringDistribution

 

通過上面的jmap應該可以看出我的機器上的MinHeapFreeRatio和MaxHeapFreeRatio分別為40個70,也就是大家經常說的在GC後剩餘空間小於40%時capacity開始增大,而大於70%時減小,由於我們不希望讓它移動,所以這兩個參數幾乎沒有意義,如果你需要設置就設置參數為:

-XX:MinHeapFreeRatio=40
-XX:MaxHeapFreeRatio=70

 

JDK 1.6後有一個動態調節板塊的,當然如果你的每一個板塊都是設置固定值,這個參數也沒有用,不過如果是非固定的,建議還是不要動態調整,預設是開啟的,建議將其關掉,參數為:

-XX:+UseAdaptiveSizepollcy 建議使用-XX:-UseAdaptiveSizepollcy關掉,為什麼當你的參數設置了NewRatio、Survivor、MaxTenuringThreshold這幾個參數如果在啟動了動態更新情況下,是無效的,當然如果你設置-Xmn是有效的,但是如果設置的比例的話,初始化可能會按照你的參數去運行,不過運行過程中會通過一定的演算法動態修改,監控中你可能會發現這些參數會發生改變,甚至於S0和S1的大小不一樣。

如果啟動了這個參數,又想要跟蹤變化,那麼就使用參數:-XX:+PrintAdaptiveSizePolicy

 

上面已經提到,javaNIO中通過Direct記憶體來提高性能,這個區域的大小預設是64M,在適當的場景可以設置大一些。

-XX:MaxDirectMemorySize

 

一個不太常用的參數:

-XX:+ScavengeBeforeFullGC 預設是開啟狀態,在full GC前先進行minor GC。

 

對於java堆中如果要設置大頁記憶體,可以通過設置參數:

付:此參數必須在操作系統的內核支持的基礎上,需要在OS級別做操作為:

echo 1024 > /proc/sys/vm/nr_hugepages

echo 2147483647 > /proc/sys/kernel/shmmax

-XX:+UseLargePages

-XX:LargePageSizeInBytes

此時整個JVM都將在這塊記憶體中,否則全部不在這塊記憶體中。

 

javaIO的臨時目錄設置

-Djava.io.tmpdir

jstack會去尋找/tmp/hsperfdata_admin下去尋找與進程號相同的文件,32位機器上是沒有問題的,64為機器的是有BUG的,在jdk 1.6u23版本中已經修複了這個bug,如果你遇到這個問題,就需要升級JDK了。

 

還記得上次說的平均晉升大小嗎,在並行GC時,如果平均晉升大小大於old剩餘空間,則發生full GC,那麼當小於剩餘空間時,也就是平均晉升小於剩餘空間,但是剩餘空間小於eden + 一個survivor的空間時,此時就依賴於參數:

-XX:-HandlePromotionFailure

啟動該參數時,上述情況成立就發生minor gc(YGC),大於則發生full gc(major gc)。

 

一般預設直接分配的對象如果大於Eden的一半就會直接晉升到old區域,但是也可以通過參數來指定:

-XX:PretenureSizeThreshold=2m 我個人不建議使用這個參數

也就是當申請對象大於這個值就會晉升到old區域。

 

傳說中GC時間的限制,一個是通過比例限制,一個是通過最大暫停時間限制,但是GC時間能限制麽,呵呵,在增量中貌似可以限制,不過不能限制住GC總體的時間,所以這個參數也不是那麼關鍵。

-XX:GCTimeRatio=

-XX:MaxGCPauseMillis

-XX:GCTimeLimit

要看到真正暫停的時間就一個是看GCDetail的日誌,另一個是設置參數看:

-XX:+PrintGCApplicationStoppedTime

 

有些人,有些人就是喜歡在代碼裡面裡頭寫System.gc(),耍酷,這個不是測試程式是線上業務,這樣將會導致N多的問題,不多說了,你應該懂的,不懂的話看下書吧,而RMI是很不聽話的一個鳥玩意,EJB的框架也是基於RMI寫的,RMI為什麼不聽話呢,就是它自己在裡面非要搞個System.gc(),哎,為了放置頻繁的做,頻繁的做,你就將這個命令的執行禁用掉吧,當然程式不用改,不然那些EJB都跑步起來了,呵呵:

-XX:+DisableExplicitGC 預設是沒有禁用掉,寫成+就是禁用掉的了,但是有些時候在使用allocateDirect的時候,很多時候還真需要System.gc來強制回收這塊資源。

 

記憶體溢出時導出溢出的錯誤信息:
-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=/home/xieyu/logs/ 這個參數指定導出時的路徑,不然導出的路徑就是虛擬機的目標位置,不好找了,預設的文件名是:java_pid<進程號>.hprof,這個文件可以類似使用jmap -dump:file=....,format=b <pid>來dump類似的內容,文件尾碼都是hprof,然後下載mat工具進行分析即可(不過記憶體有多大dump文件就多大,而本地分析的時候記憶體也需要那麼大,所以很多時候下載到本地都無法啟動是很正常的),後續文章有機會我們來說明這些工具,另外jmap -dump參數也不要經常用,會導致應用掛起哦;另外此參數只會在第一次輸出OOM的時候才會進行堆的dump操作(java heap的溢出是可以繼續運行再運行的程式的,至於web應用是否服務要看應用伺服器自身如何處理,而c heap區域的溢出就根本沒有dump的機會,因為直接就宕機了,目前系統無法看到c heap的大小以及內部變化,要看大小隻能間接通過看JVM進程的記憶體大小(top或類似參數),這個大小一般會大於heap+perm的大小,多餘的部分基本就可以認為是c heap的大小了,而看內部變化呢只有google perftools可以達到這個目的),如果記憶體過大這個dump操作將會非常長,所以hotspot如果以後想管理大記憶體,這塊必須有新的辦法出來。

最後,用dump出來的文件,通過mat分析出來的結果往往有些時候難以直接確定到底哪裡有問題,可以看到的維度大概有:那個類使用的記憶體最多,以及每一個線程使用的記憶體,以及線程內部每一個調用的類和方法所使用的記憶體,但是很多時候無法判定到底是程式什麼地方調用了這個類或者方法,因為這裡只能看到最終消耗記憶體的類,但是不知道誰使用了它,一個辦法是掃描代碼,但是太笨重,而且如果是jar包中調用了就不好弄了,另一種方法是寫agent,那麼就需要相應的配合了,但是有一個非常好的工具就是btrace工具(jdk 1.7貌似還不支持),可以跟蹤到某個類的某個方法被那些類中的方法調用過,那這個問題就好說了,只要知道開銷記憶體的是哪一個類,就能知道誰調用過它,OK,關於btrace的不是本文重點,網上都有,後續文章有機會再探討,
原理:
No performance impact during runtime(無性能影響)
Dumping a –Xmx512m heap
Create a 512MB .hprof file(512M記憶體就dump出512M的空間大小)
JVM is “dead” during dumping(死掉時dump)
Restarting JVM during this dump will cause unusable .hprof file(重啟導致文件不可用)

 

註明的NUMA架構,在JVM中開始支持,當然也需要CPU和OS的支持才可以,需要設置參數為:

-XX:+UseNUMA 必須在並行GC的基礎上才有的

老年代無法分配區域的最大等待時間為(預設值為0,但是也不要去動它):

-XX:GCExpandToAllocateDelayMillis

讓JVM中所有的set和get方法轉換為本地代碼:

-XX:+UseFastAccessorMethods

以時間戳輸出Heap的利用率

-XX:+PrintHeapUsageOverTime

在64bit的OS上面(其實一般達不到57位左右),由於指針會放大為8個byte,所以會導致空間使用增加,當然,如果記憶體夠大,就沒有問題,但是如果升級到64bit系統後,只是想讓記憶體達到4G或者8G,那麼就完全可以通過很多指針壓縮為4byte就OK了,所以在提供以下參數(本參數於jdk 1.6u23後使用,並自動開啟,所以也不需要你設置,知道就OK):

-XX:+UseCompressedOops 請註意:這個參數預設在64bit的環境下預設啟動,但是如果JVM的記憶體達到32G後,這個參數就會預設為不啟動,因為32G記憶體後,壓縮就沒有多大必要了,要管理那麼大的記憶體指針也需要很大的寬度了。

後臺JIT編譯優化啟動

-XX:+BackgroundCompilation

如果你要輸出GC的日誌以及時間戳,相關的參數有:

-XX:+PrintGCDetails 輸出GC的日誌詳情,包含了時間戳

-XX:+PrintGCTimeStamps 輸出GC的時間戳信息,按照啟動JVM後相對時間的每次GC的相對秒值(毫秒在小數點後面),也就是每次GC相對啟動JVM啟動了多少秒後發生了這次GC

-XX:+PrintGCDateStamps輸出GC的時間信息,會按照系統格式的日期輸出每次GC的時間

-XX:+PrintGCTaskTimeStamps輸出任務的時間戳信息,這個細節上比較複雜,後續有文章來探討。

-XX:-TraceClassLoading 跟蹤類的裝載

-XX:-TraceClassUnloading 跟蹤類的卸載

-XX:+PrintHeapAtGC 輸出GC後各個堆板塊的大小。

將常量信息GC信息輸出到日誌文件:

-Xloggc:/home/xieyu/logs/gc.log

 

 

現在面對大記憶體比較流行是是CMS GC(最少1.5才支持),首先明白CMS的全稱是什麼,不是傳統意義上的內容管理系統(Content Management System)哈,第一次我也沒看懂,它的全稱是:Concurrent Mark Sweep,三個單詞分別代表併發、標記、清掃(主意這裡沒有compact操作,其實CMS GC的確沒有compact操作),也就是在程式運行的同時進行標記和清掃工作,至於它的原理前面有提及過,只是有不同的廠商在上面做了一些特殊的優化,比如一些廠商在標記根節點的過程中,標記完當前的根,那麼這個根下麵的內容就不會被暫停恢復運行了,而移動過程中,通過讀屏障來看這個記憶體是不是發生移動,如果在移動稍微停一下,移動過去後再使用,hotspot還沒這麼厲害,暫停時間還是挺長的,只是相對其他的GC策略在面對大記憶體來講是不錯的選擇。

 

下麵看一些CMS的策略(併發GC總時間會比常規的並行GC長,因為它是在運行時去做GC,很多資源徵用都會影響其GC的效率,而總體的暫停時間會短暫很多很多,其並行線程數預設為:(上面設置的並行線程數 + 3)/ 4

 

付:CMS是目前Hotspot管理大記憶體最好的JVM,如果是常規的JVM,最佳選擇為ParallelOldGC,如果必須要以響應時間為準,則選擇CMS,不過CMS有兩個隱藏的隱患:

1、CMS GC雖然是併發且並行運行的GC,但是初始化的時候如果採用預設值92%(JVM 1.5的白皮書上描述為68%其實是錯誤的,1.6是正確的),就很容易出現問題,因為CMS GC僅僅針對Old區域,Yong區域使用ParNew演算法,也就是Old的CMS回收和Yong的回收可以同時進行,也就是回收過程中Yong有可能會晉升對象Old,並且業務也可以同時運行,所以92%基本開始啟動CMS GC很有可能old的記憶體就不夠用了,當記憶體不夠用的時候,就啟動Full GC,並且這個Full GC是串列的,所以如果弄的不好,CMS會比並行GC更加慢,為什麼要啟用串列是因為CMS GC、並行GC、串列GC的繼承關係決定的,簡單說就是它沒辦法去調用並行GC的代碼,細節說後續有文章來細節說明),建議這個值設置為70%左右吧,不過具體時間還是自己決定。

2、CMS GC另一個大的隱患,其實不看也差不多應該清楚,看名字就知道,就是不會做Compact操作,它最噁心的地方也在這裡,所以上面才說一般的應用都不使用它,它只有記憶體垃圾非常多,多得無法分配晉升的空間的時候才會出現一次compact,但是這個是Full GC,也就是上面的串列,很恐怖的,所以記憶體不是很大的,不要考慮使用它,而且它的演算法十分複雜。

 

還有一些小的隱患是:和應用一起徵用CPU(不過這個不是大問題,增加CPU即可)、整個運行過程中時間比並行GC長(這個也不是大問題,因為我們更加關心暫停時間而不是運行時間,因為暫停會影響非常多的業務)。

啟動CMS為全局GC方法(註意這個參數也不能上面的並行GC進行混淆,Yong預設是並行的,上面已經說過

-XX:+UseConcMarkSweepGC

在併發GC下啟動增量模式,只能在CMS GC下這個參數才有效。

-XX:+CMSIncrementalMode

啟動自動調節duty cycle,即在CMS GC中發生的時間比率設置,也就是說這段時間內最大允許發生多長時間的GC工作是可以調整的。

-XX:+CMSIncrementalPacing

在上面這個參數設定後可以分別設置以下兩個參數(參數設置的比率,範圍為0-100):

-XX:CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10

增量GC上還有一個保護因數(CMSIncrementalSafetyFactor),不太常用;CMSIncrementalOffset提供增量GC連續時間比率的設置;CMSExpAvgFactor為增量併發的GC增加權重計算。

-XX:CMSIncrementalSafetyFactor=
-XX:CMSIncrementalOffset= 
-XX:CMSExpAvgFactor=

 

是否啟動並行CMS GC(預設也是開啟的)

-XX:+CMSParallelRemarkEnabled

要單獨對CMS GC設置並行線程數就設置(預設也不需要設置):

-XX:ParallelCMSThreads

 

對PernGen進行垃圾回收:

JDK 1.5在CMS GC基礎上需要設置參數(也就是前提是CMS GC才有):

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

1.6以後的版本無需設置:-XX:+CMSPermGenSweepingEnabled,註意,其實一直以來Full GC都會觸發對Perm的回收過程,CMS GC需要有一些特殊照顧,雖然VM會對這塊區域回收,但是Perm回收的條件幾乎不太可能實現,首先需要這個類的classloader必須死掉,才可以將該classloader下所有的class幹掉,也就是要麼全部死掉,要麼全部活著;另外,這個classloader下的class沒有任何object在使用,這個也太苛刻了吧,因為常規的對象申請都是通過系統預設的,應用伺服器也有自己預設的classloader,要讓它死掉可能性不大,如果這都死掉了,系統也應該快掛了。

 

CMS GC因為是在程式運行時進行GC,不會暫停,所以不能等到不夠用的時候才去開啟GC,官方說法是他們的預設值是68%,但是可惜的是文檔寫錯了,經過很多測試和源碼驗證這個參數應該是在92%的時候被啟動,雖然還有8%的空間,但是還是很可憐了,當CMS發現記憶體實在不夠的時候又回到常規的並行GC,所以很多人在沒有設置這個參數的時候發現CMS GC並沒有神馬優勢嘛,和並行GC一個鳥樣子甚至於更加慢,所以這個時候需要設置參數(這個參數在上面已經說過,啟動CMS一定要設置這個參數):

-XX:CMSInitiatingOccupancyFraction=70

這樣保證Old的記憶體在使用到70%的時候,就開始啟動CMS了;如果你真的想看看預設值,那麼就使用參數:-XX:+PrintCMSInitiationStatistics 這個變數只有JDK 1.6可以使用 1.5不可以,查看實際值-XX:+PrintCMSStatistics;另外,還可以設置參數-XX:CMSInitiatingPermOccupancyFraction來設置Perm空間達到多少時啟動CMS GC,不過意義不大。

JDK 1.6以後有些時候啟動CMS GC是根據計算代價進行啟動,也就是不一定按照你指定的參數來設置的,如果你不想讓它按照所謂的成本來計算GC的話,那麼你就使用一個參數:-XX:+UseCMSInitiatingOccupancyOnly,預設是false,它就只會按照你設置的比率來啟動CMS GC了。如果你的程式中有System.gc以及設置了ExplicitGCInvokesConcurrent在jdk 1.6中,這種情況使用NIO是有可能產生問題的。

 

啟動CMS GC的compation操作,也就是發生多少次後做一次全局的compaction:

-XX:+UseCMSCompactAtFullCollection

-XX:CMSFullGCsBeforeCompaction:發生多少次CMS Full GC,這個參數最好不要設置,因為要做compaction的話,也就是真正的Full GC是串列的,非常慢,讓它自己去決定什麼時候需要做compaction。

 

-XX:CMSMaxAbortablePrecleanTime=5000 設置preclean步驟的超時時間,單位為毫秒,preclean為cms gc其中一個步驟,關於cms gc步驟比較多,本文就不細節探討了。

 

並行GC在mark階段,可能會同時發生minor GC,old區域也可能發生改變,於是併發GC會對發生了改變的內容進行remark操作,這個觸發的條件是:

-XX:CMSScheduleRemarkEdenSizeThreshold

-XX:CMSScheduleRemarkEdenPenetration

即Eden區域多大的時候開始觸發,和eden使用量超過百分比多少的時候觸發,前者預設是2M,後者預設是50%。

但是如果長期不做remark導致old做不了,可以設置超時,這個超時預設是5秒,可以通過參數:

-XX:CMSMaxAbortablePrecleanTime

-XX:+ExplicitGCInvokesConcurrent 在顯示發生GC的時候,允許進行並行GC。

-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 幾乎和上面一樣,只不過多一個對Perm區域的回收而已。

 

補充:

其實JVM還有很多的版本,很多的廠商,與其優化的原則,隨便舉兩個例子hotspot在GC中做的一些優化(這裡不說代碼的編譯時優化或運行時優化):

Eden申請的空間對象由Old區域的某個對象的一個屬性指向(也就是Old區域的這個空間不回收,Eden這塊就沒有必要考慮回收),所以Hotspot在CPU寫上面,做了一個屏障,當發生賦值語句的時候(對記憶體來講賦值就是一種寫操作),如果發現是一個新的對象由Old指向Eden,那麼就會將這個對象記錄在一個卡片機裡面,這個卡片機是有很多512位元組的卡片組成,當在YGC過程中,就基本不會去移動或者管理這塊對象(付:這種卡片機會在CMS GC的演算法中使用,不過和這個卡片不是放在同一個地方的,也是CMS GC的關鍵,對於CMS GC的演算法細節描述,後續文章我們單獨說明)。

Old區域對於一些比較大的對象,JVM就不會去管理個對象,也就是compact過程中不會去移動這塊對象的區域等等吧。

 

以上大部分參數為hotspot的自帶關於性能的參數,參考版本為JDK 1.5和1.6的版本,很多為個人經驗說明,不足以說明所有問題,如果有問題,歡迎探討;另外,JDK的參數是不是就只有這些呢,肯定並不是,我知道的也不止這些,但是有些覺得沒必要說出來的參數和一些數學運算的參數我就不想給出來了,比如像禁用掉GC的參數有神馬意義,我們的伺服器要是把這個禁用掉幹個屁啊,呵呵,做測試還可以用這玩玩,讓它不做GC直接溢出;還有一些什麼計算因數啥的,還有很多複雜的數學運算規則,要是把這個配置明白了,就太那個了,而且一般情況下也沒那個必要,JDK到現在的配置參數多達上500個以上,要知道完的話慢慢看吧,不過意義不大,而且要知道預設值最靠譜的是看源碼而不是看文檔,官方文檔也只能保證絕大部是正確的,不能保證所有的是正確的。

 

 

本文最後追加在jdk 1.6u 24後通過上面說明的-XX:+PrintFlagsFinal輸出的參數以及預設值(還是那句話,在不同的平臺上是不一樣的),輸出的參數如下,可以看看JVM的參數是相當的多,參數如此之多,你只需要掌握關鍵即可,參數還有很多有衝突的,不要糾結於每一個參數的細節:

$java -XX:+PrintFlagsFinal

uintx AdaptivePermSizeWeight = 20 {product}
uintx AdaptiveSizeDecrementScaleFactor = 4 {product}
uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product}
uintx AdaptiveSizePausePolicy = 0 {product}
uintx AdaptiveSizePolicyCollectionCostMargin = 50 {product}
uintx AdaptiveSizePolicyInitializingSteps = 20 {product}
uintx AdaptiveSizePolicyOutputInterval = 0 {product}
uintx AdaptiveSizePolicyWeight = 10 {product}
uintx AdaptiveSizeThroughPutPolicy = 0 {product}
uintx AdaptiveTimeWeight = 25 {product}
bool AdjustConcurrency = false {product}
bool AggressiveOpts = false {product}
intx AliasLevel = 3 {product}
intx AllocatePrefetchDistance = -1 {product}
intx AllocatePrefetchInstr = 0 {product}
intx AllocatePrefetchLines = 1 {product}
intx AllocatePrefetchStepSize = 16 {product}
intx AllocatePrefetchStyle = 1 {product}
bool AllowJNIEnvProxy = false {product}
bool AllowParallelDefineClass = false {product}
bool AllowUserSignalHandlers = false {product}
bool AlwaysActAsServerClassMachine = false {product}
bool AlwaysCompileLoopMethods = false {product}
intx AlwaysInflate = 0 {product}
bool AlwaysLockClassLoader = false {product}
bool AlwaysPreTouch = false {product}
bool AlwaysRestoreFPU = false {product}
bool AlwaysTenure = false {product}
bool AnonymousClasses = false {product}
bool AssertOnSuspendWaitFailure = false {product}
intx Atomics = 0 {product}
uintx AutoGCSelectPauseMillis = 5000 {product}
intx BCEATraceLevel = 0 {product}
intx BackEdgeThreshold = 100000 {pd product}
bool BackgroundCompilation = true {pd product}
uintx BaseFootPrintEstimate = 268435456 {product}
intx BiasedLockingBulkRebiasThreshold = 20 {product}
intx BiasedLockingBulkRevokeThreshold = 40 {product}
intx BiasedLockingDecayTime = 25000 {product}
intx BiasedLockingStartupDelay = 4000 {product}
bool BindGCTaskThreadsToCPUs = false {product}
bool BlockOffsetArrayUseUnallocatedBlock = false {product}
bool BytecodeVerificationLocal = false {product}
bool BytecodeVerificationRemote = true {product}
intx CICompilerCount = 1 {product}
bool CICompilerCountPerCPU = false {product}
bool CITime = false {product}
bool CMSAbortSemantics = false {product}
uintx CMSAbortablePrecleanMinWorkPerIteration = 100 {product}
intx CMSAbortablePrecleanWaitMillis = 100 {product}
uintx CMSBitMapYieldQuantum = 10485760 {product}
uintx CMSBootstrapOccupancy = 50 {product}
bool CMSClassUnloadingEnabled = false {product}
uintx CMSClassUnloadingMaxInterval = 0 {product}
bool CMSCleanOnEnter = true {product}
bool CMSCompactWhenClearAllSoftRefs = true {product}
uintx CMSConcMarkMultiple = 32 {product}
bool CMSConcurrentMTEnabled = true {product}
uintx CMSCoordinatorYieldSleepCount = 10 {product}
bool CMSDumpAtPromotionFailure = false {product}
uintx CMSExpAvgFactor = 50 {product}
bool CMSExtrapolateSweep = false {product}
uintx CMSFullGCsBeforeCompaction = 0 {product}
uintx CMSIncrementalDutyCycle = 10 {product}
uintx CMSIncrementalDutyCycleMin = 0 {product}
bool CMSIncrementalMode = false {product}
uintx CMSIncrementalOffset = 0 {product}
bool CMSIncrementalPacing = true {product}
uintx CMSIncrementalSafetyFactor = 10 {product}
uintx CMSIndexedFreeListReplenish = 4 {product}
intx CMSInitiatingOccupancyFraction = -1 {product}
intx CMSInitiatingPermOccupancyFraction = -1 {product}
intx CMSIsTooFullPercentage = 98 {product}
double CMSLargeCoalSurplusPercent = {product}
double CMSLargeSplitSurplusPercent = {product}
bool CMSLoopWarn = false {product}
uintx CMSMaxAbortablePrecleanLoops = 0 {product}
intx CMSMaxAbortablePrecleanTime = 5000 {product}
uintx CMSOldPLABMax = 1024 {product}
uintx CMSOldPLABMin = 16 {product}
uintx CMSOldPLABNumRefills = 4 {product}
uintx CMSOldPLABReactivityCeiling = 10 {product}
uintx CMSOldPLABReactivityFactor = 2 {product}
bool CMSOldPLABResizeQuicker = false {product}
uintx CMSOldPLABToleranceFactor = 4 {product}
bool CMSPLABRecordAlways = true {product}
uintx CMSParPromoteBlocksToClaim = 16 {product}
bool CMSParallelRemarkEnabled = true {product}
bool CMSParallelSurvivorRemarkEnabled = true {product}
bool CMSPermGenPrecleaningEnabled = true {product}
uintx CMSPrecleanDenominator = 3 {product}
uintx CMSPrecleanIter = 3 {product}
uintx CMSPrecleanNumerator = 2 {product}
bool CMSPrecleanRefLists1 = true {product}
bool CMSPrecleanRefLists2 = false {product}
bool CMSPrecleanSurvivors1 = false {product}
bool CMSPrecleanSurvivors2 = true {product}
uintx CMSPrecleanThreshold = 1000 {product}
bool CMSPrecleaningEnabled = true {product}
bool CMSPrintChunksInDump = false {product}
bool CMSPrintObjectsInDump = false {product}
uintx CMSRemarkVerifyVariant = 1 {product}
bool CMSReplenishIntermediate = true {product}
uintx CMSRescanMultiple = 32 {product}
uintx CMSRevisitStackSize = 1048576 {product}
uintx CMSSamplingGrain = 16384 {product}
bool CMSScavengeBeforeRemark = false {product}
uintx CMSScheduleRemarkEdenPenetration = 50 {product}
uintx CMSScheduleRemarkEdenSizeThreshold = 2097152 {product}
uintx CMSScheduleRemarkSamplingRatio = 5 {product}
double CMSSmallCoalSurplusPercent = {product}
double CMSSmallSplitSurplusPercent = {product}
bool CMSSplitIndexedFreeListBlocks = true {product}
intx CMSTriggerPermRatio = 80 {product}
intx CMSTriggerRatio = 80 {product}
bool CMSUseOldDefaults = false {product}
intx CMSWaitDuration = 2000 {product}
uintx CMSWorkQueueDrainThreshold = 10 {product}
bool CMSYield = true {product}
uintx CMSYieldSleepCount = 0 {product}
intx CMSYoungGenPerWorker = 16777216 {product}
uintx CMS_FLSPadding = 1 {product}
uintx CMS_FLSWeight = 75 {product}
uintx CMS_SweepPadding = 1 {product}
uintx CMS_SweepTimerThresholdMillis = 10 {product}
uintx CMS_SweepWeight = 75 {product}
bool CheckJNICalls = false {product}
bool ClassUnloading = true {product}
intx ClearFPUAtPark = 0 {product}
bool ClipInlining = true {product}
uintx CodeCacheExpansionSize = 32768 {pd product}
uintx CodeCacheFlushingMinimumFreeSpace = 1536000 {product}
uintx CodeCacheMinimumFreeSpace = 512000 {product}
bool CollectGen0First = false {product}
bool CompactFields = true {product}
intx CompilationPolicyChoice = 0 {product}
intx CompilationRepeat = 0 {C1 product}
ccstrlist CompileCommand = {product}
ccstr CompileCommandFile = {product}
ccstrlist CompileOnly = {product}
intx CompileThreshold = 1500 {pd product}
bool CompilerThreadHintNoPreempt = true {product}
intx CompilerThreadPriority = -1 {product}
intx CompilerThreadStackSize = 0 {pd product}
uintx ConcGCThreads = 0 {product}
bool ConvertSleepToYield = true {pd product}
bool ConvertYieldToSleep = false {product}
bool DTraceAllocProbes = false {product}
bool DTraceMethodProbes = false {product}
bool DTraceMonitorProbes = false {product}
uintx DefaultMaxRAMFraction = 4 {product}
intx DefaultThreadPriority = -1 {product}
intx DeferPollingPageLoopCount = -1 {product}
intx DeferThrSuspendLoopCount = 4000 {product}
bool DeoptimizeRandom = false {product}
bool DisableAttachMechanism = false {product}
bool DisableExplicitGC = false {product}
bool DisplayVMOutputToStderr = false {product}
bool DisplayVMOutputToStdout = false {product}
bool DontCompileHugeMethods = true {product}
bool DontYieldALot = false {pd product}
bool DumpSharedSpaces = false {product}
bool EagerXrunInit = false {product}
intx EmitSync = 0 {product}
uintx ErgoHeapSizeLimit = 0 {product}
ccstr ErrorFile = {product}
bool EstimateArgEscape = true {product}
intx EventLogLength = 2000 {product}
bool ExplicitGCInvokesConcurrent = false {product}
bool ExplicitGCInvokesConcurrentAndUnloadsClasses = false {produ
bool ExtendedDTraceProbes = false {product}
bool FLSAlwaysCoalesceLarge = false {product}
uintx FLSCoalescePolicy = 2 {product}
double FLSLargestBlockCoalesceProximity = {product}
bool FailOverToOldVerifier = true {product}
bool FastTLABRefill = true {product}
intx FenceInstruction = 0 {product}
intx FieldsAllocationStyle = 1 {product}
bool FilterSpuriousWakeups = true {product}
bool ForceFullGCJVMTIEpilogues = false {product}
bool ForceNUMA = false {product}
bool ForceSharedSpaces = false {product}
bool ForceTimeHighResolution = false {product}
intx FreqInlineSize = 325 {pd product}
intx G1ConcRefinementGreenZone = 0 {product}
intx G1ConcRefinementRedZone = 0 {product}
intx G1ConcRefinementServiceIntervalMillis = 300 {product}
uintx G1ConcRefinementThreads = 0 {product}
intx G1ConcRefinementThresholdStep = 0 {product}
intx G1ConcRefinementYellowZone = 0 {product}
intx G1ConfidencePercent = 50 {product}
uintx G1HeapRegionSize = 0 {product}
intx G1MarkRegionStackSize = 1048576 {product}
intx G1RSetRegionEntries = 0 {product}
uintx G1RSetScanBlockSize = 64 {product}
intx G1RSetSparseRegionEntries = 0 {product}
intx G1RSetUpdatingPauseTimePercent = 10 {product}
intx G1ReservePercent = 10 {product}
intx G1SATBBufferSize = 1024 {product}
intx G1UpdateBufferSize = 256 {product}
bool G1UseAdaptiveConcRefinement = true {product}
bool G1UseFixedWindowMMUTracker = false {product}
uintx GCDrainStackTargetSize = 64 {product}
uintx GCHeapFreeLimit = 2 {product}
bool GCLockerInvokesConcurrent = false {product}
bool GCOverheadReporting = false {product}
intx GCOverheadReportingPeriodMS = 100 {product}
intx GCPauseIntervalMillis = 500 {product}
uintx GCTaskTimeStampEntries = 200 {product}
uintx GCTimeLimit = 98 {product}
uintx GCTimeRatio = 99 {product}
ccstr HPILibPath = {product}
bool HandlePromotionFailure = true {product}
uintx HeapBaseMinAddress = 2147483648 {pd product}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
bool HeapDumpOnOutOfMemoryError = false {manageable}
ccstr HeapDumpPath = {manageable}
uintx HeapFirstMaximumCompactionCount = 3 {product}
uintx HeapMaximumCompactionInterval = 20 {product}
bool IgnoreUnrecognizedVMOptions = false {product}
uintx InitialCodeCacheSize = 163840 {pd product}
uintx InitialHeapSize := 16777216 {product}
uintx InitialRAMFraction = 64 {product}
uintx InitialSurvivorRatio = 8 {product}
intx InitialTenuringThreshold = 7 {product}
uintx InitiatingHeapOccupancyPercent = 45 {product}
bool Inline = true {product}
intx InlineSmallCode = 1000 {pd product}
intx InterpreterProfilePercentage = 33 {product}
bool JNIDetachReleasesMonitors = true {product}
bool JavaMonitorsInStackTrace = true {product}
intx JavaPriority10_To_OSPriority = -1 {product}
intx JavaPriority1_To_OSPriority = -1 {product}
intx JavaPriority2_To_OSPriority = -1 {product}
intx JavaPriority3_To_OSPriority = -1 {product}
intx JavaPriority4_To_OSPriority = -1 {product}
intx JavaPriority5_To_OSPriority = -1 {product}
intx JavaPriority6_To_OSPriority = -1 {product}
intx JavaPriority7_To_OSPriority = -1 {product}
intx JavaPriority8_To_OSPriority = -1 {product}
intx JavaPriority9_To_OSPriority = -1 {product}
bool LIRFillDelaySlots = false {C1 pd product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx LargePageSizeInBytes = 0 {product}
bool LazyBootClassLoader = true {product}
bool ManagementServer = false {product}
uintx MarkStackSize = 32768 {product}
uintx MarkStackSizeMax = 4194304 {product}
intx MarkSweepAlwaysCompactCount = 4 {product}
uintx MarkSweepDeadRatio = 5 {product}
intx MaxBCEAEstimateLevel = 5 {product}
intx MaxBCEAEstimateSize = 150 {product}
intx MaxDirectMemorySize = -1 {product}
bool MaxFDLimit = true {product}
uintx MaxGCMinorPauseMillis = 4294967295 {product}
uintx MaxGCPauseMillis = 4294967295 {product}
uintx MaxHeapFreeRatio = 70 {product}
uintx MaxHeapSize := 268435456 {product}
intx MaxInlineLevel = 9 {product}
intx MaxInlineSize = 35 {product}
intx MaxJavaStackTraceDepth = 1024 {product}
uintx MaxLiveObjectEvacuationRatio = 100 {product}
uintx MaxNewSize = 4294967295 {product}
uintx MaxPermHeapExpansion = 4194304 {product}
uintx MaxPermSize = 67108864 {pd product}
uint64_t MaxRAM = 1073741824 {pd product}
uintx MaxRAMFraction = 4 {product}
intx MaxRecursiveInlineLevel = 1 {product}
intx MaxTenuringThreshold = 15 {product}
intx MaxTrivialSize = 6 {product}
bool MethodFlushing = true {product}
intx MinCodeCacheFlushingInterval = 30 {product}
uintx MinHeapDeltaBytes = 131072 {product}
uintx MinHeapFreeRatio = 40 {product}
intx MinInliningThreshold = 250 {product}
uintx MinPermHeapExpansion = 262144 {product}
uintx MinRAMFraction = 2 {product}
uintx MinSurvivorRatio = 3 {product}
uintx MinTLABSize = 2048 {product}
intx MonitorBound = 0 {product}
bool MonitorInUseLists = false {product}
bool MustCallLoadClassInternal = false {product}
intx NUMAChunkResizeWeight = 20 {product}
intx NUMAPageScanRate = 256 {product}
intx NUMASpaceResizeRate = 1073741824 {product}
bool NUMAStats = false {product}
intx NativeMonitorFlags = 0 {product}
intx NativeMonitorSpinLimit = 20 {product}
intx NativeMonitorTimeout = -1 {product}
bool NeedsDeoptSuspend = false {pd product}
bool NeverActAsServerClassMachine = true {pd product}
bool NeverTenure = false {product}
intx NewRatio = 2 {product}
uintx NewSize = 1048576 {product}
uintx NewSizeThreadIncrease = 4096 {pd product}
intx NmethodSweepFraction = 4 {product}
uintx OldPLABSize = 1024 {product}
uintx OldPLABWeight = 50 {product}
uintx OldSize = 4194304 {product}
bool OmitStackTraceInFastThrow = true {product}
ccstrlist OnError = {product}
ccstrlist OnOutOfMemoryError = {product}
intx OnStackReplacePercentage = 933 {pd product}
uintx PLABWeight = 75 {product}
bool PSChunkLargeArrays = true {product}
intx ParGCArrayScanChunk = 50 {product}
uintx ParGCDesiredObjsFromOverflowList = 20 {product}
bool ParGCTrimOverflow = true {product}
bool ParGCUseLocalOverflow = false {product}
intx ParallelGCBufferWastePct = 10 {product}
bool ParallelGCRetainPLAB = true {product}
uintx ParallelGCThreads = 0 {product}
bool ParallelGCVerbose = false {product}
uintx ParallelOldDeadWoodLimiterMean = 50 {product}
uintx ParallelOldDeadWoodLimiterStdDev = 80 {product}
bool ParallelRefProcBalancingEnabled = true {product}
bool ParallelRefProcEnabled = false {product}
uintx PausePadding = 1 {product}
intx PerBytecodeRecompilationCutoff = 200 {product}
intx PerBytecodeTrapLimit = 4 {product}
intx PerMethodRecompilationCutoff = 400 {product}
intx PerMethodTrapLimit = 100 {product}
bool PerfAllowAtExitRegistration = false {product}
bool PerfBypassFileSystemCheck = false {product}
intx PerfDataMemorySize = 32768 {product}
intx PerfDataSamplingInterval = 50 {product}
ccstr PerfDataSaveFile = {product}
bool PerfDataSaveToFile = false {product}
bool PerfDisableSharedMem = false {product}
intx PerfMaxStringConstLength = 1024 {product}
uintx PermGenPadding = 3 {product}
uintx PermMarkSweepDeadRatio = 20 {product}
uintx PermSize = 12582912 {pd product}
bool PostSpinYield = true {product}
intx PreBlockSpin = 10 {product}
intx PreInflateSpin = 10 {pd product}
bool PreSpinYield = false {product}
bool PreferInterpreterNativeStubs = false {pd product}
intx PrefetchCopyIntervalInBytes = -1 {product}
intx PrefetchFieldsAhead = -1 {product}
intx PrefetchScanIntervalInBytes = -1 {product}
bool PreserveAllAnnotations = false {product}
uintx PreserveMarkStackSize = 1024 {product}
uintx PretenureSizeThreshold = 0 {product}
bool PrintAdaptiveSizePolicy = false {product}
bool PrintCMSInitiationStatistics = false {product}
intx PrintCMSStatistics = 0 {product}
bool PrintClassHistogram = false {manageable}
bool PrintClassHistogramAfterFullGC = false {manageable}
bool PrintClassHistogramBeforeFullGC = false {manageable}
bool PrintCommandLineFlags = false {product}
bool PrintCompilation = false {product}
bool PrintConcurrentLocks = false {manageable}
intx PrintFLSCensus = 0 {product}
intx PrintFLSStatistics = 0 {product}
bool PrintFlagsFinal := true {product}
bool PrintFlagsInitial = false {product}
bool PrintGC = false {manageable}
bool PrintGCApplicationConcurrentTime = false {product}
bool PrintGCApplicationStoppedTime = false {product}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCTaskTimeStamps = false {product}
bool PrintGCTimeStamps = false {manageable}
bool PrintHeapAtGC = false {product rw}
bool PrintHeapAtGCExtended = false {product rw}
bool PrintHeapAtSIGBREAK = true {product}
bool PrintJNIGCStalls = false {product}
bool PrintJNIResolving = false {product}
bool PrintOldPLAB = false {product}
bool PrintPLAB = false {product}
bool PrintParallelOldGCPhaseTimes = false {product}
bool PrintPromotionFailure = false {product}
bool PrintReferenceGC = false {product}
bool PrintRevisitStats = false {product}
bool PrintSafepointStatistics = false {product}
intx PrintSafepointStatisticsCount = 300 {product}
intx PrintSafepointStatisticsTimeout = -1 {product}
bool PrintSharedSpaces = false {product}
bool PrintTLAB = false {product}
bool PrintTenuringDistribution = false {product}
bool PrintVMOptions = false {product}
bool PrintVMQWaitTime = false {product}
uintx ProcessDistributionStride = 4 {product}
bool ProfileInterpreter = false {pd product}
bool ProfileIntervals = false {product}
intx ProfileIntervalsTicks = 100 {product}
intx ProfileMaturityPercentage = 20 {product}
bool ProfileVM = false {product}
bool ProfilerPrintByteCodeStatistics = false {product}
bool ProfilerRecordPC = false {product}
uintx PromotedPadding = 3 {product}
intx QueuedAllocationWarningCount = 0 {product}
bool RangeCheckElimination = true {product}
intx ReadPrefetchInstr = 0 {product}
intx ReadSpinIterations = 100 {product}
bool ReduceSignalUsage = false {product}
intx RefDiscoveryPolicy = 0 {product}
bool ReflectionWrapResolutionErrors = true {product}
bool RegisterFinalizersAtInit = true {product}
bool RelaxAccessControlCheck = false {product}
bool RequireSharedSpaces = false {product}
uintx ReservedCodeCacheSize = 33554432 {pd product}
bool ResizeOldPLAB = true {product}
bool ResizePLAB = true {product}
bool ResizeTLAB = true {pd product}
bool RestoreMXCSROnJNICalls = false {product}
bool RewriteBytecodes = false {pd product}
bool RewriteFrequentPairs = false {pd product}
intx SafepointPollOffset = 256 {C1 pd product}
intx SafepointSpinBeforeYield = 2000 {product}
bool SafepointTimeout = false {product}
intx SafepointTimeoutDelay = 10000 {product}
bool ScavengeBeforeFullGC = true {product}
intx SelfDestructTimer = 0 {product}
uintx SharedDummyBlockSize = 536870912 {product}
uintx SharedMiscCodeSize = 4194304 {product}
uintx SharedMiscDataSize = 4194304 {product}
uintx SharedReadOnlySize = 10485760 {product}
uintx SharedReadWriteSize = 12582912 {product}
bool ShowMessageBoxOnError = false {product}
intx SoftRefLRUPolicyMSPerMB = 1000 {product}
bool SplitIfBlocks = true {product}
intx StackRedPages = 1 {pd product}
intx StackShadowPages = 3 {pd product}
bool StackTraceInThrowable = true {product}
intx StackYellowPages = 2 {pd product}
bool StartAttachListener = false {product}
intx StarvationMonitorInterval = 200 {product}
bool StressLdcRewrite = false {product}
bool StressTieredRuntime = false {product}
bool SuppressFatalErrorMessage = false {product}
uintx SurvivorPadding = 3 {product}
intx SurvivorRatio = 8 {product}
intx SuspendRetryCount = 50 {product}
intx SuspendRetryDelay = 5 {product}
intx SyncFlags = 0 {product}
ccstr SyncKnobs = {product}
intx SyncVerbose = 0 {product}
uintx TLABAllocationWeight = 35 {product}
uintx TLABRefillWasteFraction = 64 {product}
uintx TLABSize = 0 {product}
bool TLABStats = true {product}
uintx TLABWasteIncrement = 4 {product}
uintx TLABWasteTargetPercent = 1 {product}
bool TaggedStackInterpreter = false {product}
intx TargetPLABWastePct = 10 {product}
intx TargetSurvivorRatio = 50 {product}
uintx TenuredGenerationSizeIncrement = 20 {product}
uintx TenuredGenerationSizeSupplement = 80 {product}
uintx TenuredGenerationSizeSupplementDecay = 2 {product}
intx ThreadPriorityPolicy = 0 {product}
bool ThreadPriorityVerbose = false {product}
uintx ThreadSafetyMargin = 52428800 {product}
intx ThreadStackSize = 0 {pd product}
uintx ThresholdTolerance = 10 {product}
intx Tier1BytecodeLimit = 10 {product}
bool Tier1OptimizeVirtualCallProfiling = true {C1 product}
bool Tier1ProfileBranches = true {C1 product}
bool Tier1ProfileCalls = true {C1 product}
bool Tier1ProfileCheckcasts = true {C1 product}
bool Tier1ProfileInlinedCalls = true {C1 product}
bool Tier1ProfileVirtualCalls = true {C1 product}
bool Tier1UpdateMethodData = false {product}
intx Tier2BackEdgeThreshold = 100000 {pd product}
intx Tier2CompileThreshold = 1500 {pd product}
intx Tier3BackEdgeThreshold = 100000 {pd product}
intx Tier3CompileThreshold = 2500 {pd product}
intx Tier4BackEdgeThreshold = 100000 {pd product}
intx Tier4CompileThreshold = 4500 {pd product}
bool TieredCompilation = false {pd product}
bool TimeLinearScan = false {C1 product}
bool TraceBiasedLocking = false {product}
bool TraceClassLoading = false {product rw}
bool TraceClassLoadingPreorder = false {product}
bool TraceClassResolution = false {produc

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.兩台伺服器,主伺服器,從伺服器,兩台伺服器都安裝SQL Server 2008R2並且安裝相同表結構的資料庫(需要實時同步的資料庫) 2.主伺服器資料庫安裝完畢,打開SQL Server 配置管理器,把SQL Server 代理服務打開(已打開請忽略) 3.登錄主伺服器資料庫,從資料庫左側菜單欄 ...
  • 1、進MySQL之後, 2、輸入以下語句,進入mysql庫: use mysql3、更新域屬性,'%'表示允許外部訪問: update user set host='%' where user ='root';4、執行以上語句之後再執行: FLUSH PRIVILEGES;5、再執行授權語句: GR ...
  • 事務註意事項:事務里不能包含事務,也就是說當存儲過程調用存儲過程的時候,外層存儲過程有事務時,被調用的存儲過程不能寫事務,不然事務回滾不了。 ...
  • 概述 UILabel類實現了一個只讀文本視圖。你可以使用這個類來畫一個或多個靜態文本.UILabel類支持既簡單又複雜的樣式標簽文本,還可以控制外觀,比如標簽是否使用了一個影子或者處於高亮狀態等等. UILabel類繼承自UIView 屬性 創建UILabel對象 UILabel *label = ...
  • 概述 UITextField在界面中顯示可編輯文本區域的對象。 您可以使用文本欄位來使用屏幕鍵盤從用戶收集基於文本的輸入。鍵盤可以配置許多不同類型的輸入,如純文本,電子郵件,數字等等。文本欄位使用目標操作機制和委托對象來報告在編輯過程中所做的更改。 除了基本的文本編輯行為之外,還可以將疊加視圖添加到 ...
  • https://github.com/CoderLN/Apple GitHub Codeidea Apple 譯文、GitHub 源碼,隨原作者 (大版本) 迭代註解。 "不知名開發者" https://github.com/CoderLN/Framework Codeidea iOS_12 Fra ...
  • 一. Android 中的廣播主要分兩種類型:標準廣播和有序廣播。 標準廣播(Normal broadcasts) 是一種完全非同步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播消息,因此它們之間沒有任何先後順序可 言。這種廣播的效率會比較高,但同時也意味著它是無法被截斷 ...
  • 前言:iOS開發中經常會使用到圖片和視頻上傳及保存到相冊,下麵我講介紹視頻圖片的兩種上傳伺服器的方法。以阿裡雲的OSS伺服器為例。 友情提示:上傳圖片方法在APP中使用很廣泛,最好單獨寫一個圖片上傳的類,這樣就很方便了。 base64上傳圖片:NSString *strType = [GXToolC ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...