xmx java_为什么我的Java进程比Xmx消耗更多的内存?
xmx java
你們有些人去過那里。 您已經(jīng)在啟動腳本中添加了-Xmx選項,并放松了下來,因為您知道Java進(jìn)程將不會消耗比經(jīng)過微調(diào)的選項所允許的更多的內(nèi)存。 然后,您感到非常討厭。 要么自己檢查開發(fā)/測試框中的過程表,要么事情真的變壞了,然后由操作人員在半夜打電話給您,告訴您您要生產(chǎn)的4G內(nèi)存已用完。 而且該應(yīng)用程序剛剛終止。
那么幕后到底發(fā)生了什么呢? 為什么進(jìn)程消耗的內(nèi)存比分配的更多? 是bug還是完全正常的東西? 忍受我,我將指導(dǎo)您進(jìn)行到底。
首先,它的一部分肯定可以是內(nèi)存泄漏的惡意本機(jī)代碼。 但是在99%的情況下,這完全是JVM的正常行為。 通過-Xmx開關(guān)指定的內(nèi)容是限制應(yīng)用程序堆消耗的內(nèi)存。
除了堆以外,您的應(yīng)用程序還使用內(nèi)存中的其他區(qū)域,即permgen和堆棧大小。 因此,為了限制這些值,還應(yīng)該分別指定-XX:MaxPermSize和-Xss選項。 簡而言之,您可以使用以下公式預(yù)測應(yīng)用程序的內(nèi)存使用情況
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]但是,除了您的應(yīng)用程序占用的內(nèi)存外,JVM本身還需要一些空間 。 對它的需求來自幾個不同的原因:
- 垃圾收集。 您可能還記得,Java是一種垃圾收集語言。 為了使垃圾收集器知道哪些對象適合進(jìn)行收集,它需要跟蹤對象圖。 因此,這是內(nèi)部簿記丟失的部分內(nèi)存。 特別是G1以其對額外內(nèi)存的過度需求而聞名,因此請注意這一點(diǎn)。
- JIT優(yōu)化。 Java虛擬機(jī)在運(yùn)行時優(yōu)化代碼。 同樣,要知道要優(yōu)化的部分,需要跟蹤某些代碼部分的執(zhí)行情況。 同樣,您將失去記憶。
- 堆外分配。 如果您碰巧使用了堆外內(nèi)存,例如,在自己使用直接或映射的ByteBuffer或通過一些聰明的第三方API時,那就瞧瞧-您正在將堆擴(kuò)展到實(shí)際上無法通過JVM配置控制的范圍。
- JNI代碼。 例如,當(dāng)您以2類數(shù)據(jù)庫驅(qū)動程序的格式使用本機(jī)代碼時,您將再次在本機(jī)內(nèi)存中加載代碼。
- 元空間。 如果您是Java 8的較早采用者,那么您將使用元空間而不是舊的permgen來存儲類聲明。 這是無限的,并且在JVM的本機(jī)部分中。
除了上面列出的原因之外,您最終可能還會由于其他原因而使用內(nèi)存,但是我希望我能說服您JVM內(nèi)部消耗了大量內(nèi)存。 但是,有沒有一種方法可以預(yù)測實(shí)際需要多少內(nèi)存呢? 或者至少了解它消失的位置以便進(jìn)行優(yōu)化?
正如我們從痛苦的經(jīng)歷中發(fā)現(xiàn)的那樣-無法以合理的精度進(jìn)行預(yù)測。 JVM開銷的范圍從幾個百分點(diǎn)到幾百個百分點(diǎn)。 您最好的朋友還是古老的嘗試和錯誤。 因此,您需要以類似于生產(chǎn)環(huán)境和度量的負(fù)載運(yùn)行應(yīng)用程序。
衡量額外的開銷是微不足道的–只需使用OS內(nèi)置工具(在Linux上排名靠前 ,在OS X上使用Activity Monitor ,在Windows上使用Task Manager )監(jiān)視進(jìn)程即可找出實(shí)際的內(nèi)存消耗。 從實(shí)際消耗中減去堆大小和permgen大小,您將看到開銷。
現(xiàn)在,如果需要減少開銷,您想了解它實(shí)際消失的位置。 在這種情況下,我們發(fā)現(xiàn)Mac OS X上的vmmap和Linux上的pmap是真正有用的工具。 我們自己沒有使用vmmap端口連接Windows,但似乎也有Windows迷的工具。
以下示例說明了這種情況。 我使用以下啟動參數(shù)啟動了Jetty:
-Xmx168m -Xms168m -XX:PermSize=32m -XX:MaxPermSize=32m -Xss1m知道我的應(yīng)用程序中啟動了30個線程后,我可能會希望無論如何我的內(nèi)存使用量都不會超過230M。 但是現(xiàn)在當(dāng)我在Mac OS X上查看“ 活動監(jiān)視器”時,會看到一些不同的東西。
實(shí)際內(nèi)存使用量已超過320M。 現(xiàn)在,在vmmap <pid>輸出的幫助下, 深入了解該過程,我們開始了解內(nèi)存在哪里消失。 讓我們看一些示例:
下面說我們丟失了將近2MB丟失到內(nèi)存映射的rt.jar庫。
mapped file ???????????00000001178b9000-0000000117a88000 [ 1852K] r--/r-x SM=ALI ?/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/rt.jar下一節(jié)說明,對于加載的特定動態(tài)庫,我們正在使用?6MB
__TEXT ????????????????0000000104573000-0000000104c00000 [ 6708K] r-x/rwx SM=COW ?/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/server/libjvm.dylib在這里,我們沒有線程25-30,每個線程為其堆棧和堆棧防護(hù)分配1MB
Stack 000000011a5f1000-000000011a6f0000 [ 1020K] rw-/rwx SM=ZER thread 25 Stack 000000011aa8c000-000000011ab8b000 [ 1020K] rw-/rwx SM=ZER thread 27 Stack 000000011ab8f000-000000011ac8e000 [ 1020K] rw-/rwx SM=ZER thread 28 Stack 000000011ac92000-000000011ad91000 [ 1020K] rw-/rwx SM=ZER thread 29 Stack 000000011af0f000-000000011b00e000 [ 1020K] rw-/rwx SM=ZER thread 30STACK GUARD 000000011a5ed000-000000011a5ee000 [ 4K] ---/rwx SM=NUL stack guard for thread 25 STACK GUARD 000000011aa88000-000000011aa89000 [ 4K] ---/rwx SM=NUL stack guard for thread 27 STACK GUARD 000000011ab8b000-000000011ab8c000 [ 4K] ---/rwx SM=NUL stack guard for thread 28 STACK GUARD 000000011ac8e000-000000011ac8f000 [ 4K] ---/rwx SM=NUL stack guard for thread 29 STACK GUARD 000000011af0b000-000000011af0c000 [ 4K] ---/rwx SM=NUL stack guard for thread 30 我希望我能對預(yù)測和測量實(shí)際內(nèi)存消耗這一棘手的任務(wù)有所了解。
翻譯自: https://www.javacodegeeks.com/2013/06/why-does-my-java-process-consume-more-memory-than-xmx.html
xmx java
總結(jié)
以上是生活随笔為你收集整理的xmx java_为什么我的Java进程比Xmx消耗更多的内存?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为 WATCH GT 4 手表上架预约
- 下一篇: 微软 Surface Laptop Go