JAVA進(jìn)程占用高內(nèi)存原因分析與優(yōu)化方法
來源:易賢網(wǎng) 閱讀:2246 次 日期:2014-12-02 15:11:27
溫馨提示:易賢網(wǎng)小編為您整理了“JAVA進(jìn)程占用高內(nèi)存原因分析與優(yōu)化方法”,方便廣大網(wǎng)友查閱!

首先看一下一個(gè)java進(jìn)程的jmap輸出:

代碼如下:

[lex@chou ~]$ jmap -heap 837

Attaching to process ID 837, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 20.10-b01

using thread-local object allocation.

Parallel GC with 2 thread(s)

Heap Configuration:

MinHeapFreeRatio = 40

MaxHeapFreeRatio = 70

MaxHeapSize = 4294967296 (4096.0MB)

NewSize = 1310720 (1.25MB)

MaxNewSize = 17592186044415 MB

OldSize = 5439488 (5.1875MB)

NewRatio = 2

SurvivorRatio = 8

PermSize = 21757952 (20.75MB)

MaxPermSize = 85983232 (82.0MB)

Heap Usage:

PS Young Generation

Eden Space:

capacity = 41025536 (39.125MB)

used = 18413552 (17.560531616210938MB)

free = 22611984 (21.564468383789062MB)

44.883147900858624% used

From Space:

capacity = 4325376 (4.125MB)

used = 3702784 (3.53125MB)

free = 622592 (0.59375MB)

85.60606060606061% used

To Space:

capacity = 4521984 (4.3125MB)

used = 0 (0.0MB)

free = 4521984 (4.3125MB)

0.0% used

PS Old Generation

capacity = 539820032 (514.8125MB)

used = 108786168 (103.74657440185547MB)

free = 431033864 (411.06592559814453MB)

20.152302906758376% used

PS Perm Generation

capacity = 85983232 (82.0MB)

used = 60770232 (57.95500946044922MB)

free = 25213000 (24.04499053955078MB)

70.67684080542588% used

然后再用ps看看:

代碼如下:

[lex@chou ~]$ ps -p 837 -o vsz,rss

VSZ RSS

7794992 3047320

關(guān)于這里的幾個(gè)generation網(wǎng)上資料一大把就不細(xì)說了,這里算一下求和可以得知前者總共給Java環(huán)境分配了644M的內(nèi)存,而ps輸出的VSZ和RSS分別是7.4G和2.9G,這到底是怎么回事呢?

前面jmap輸出的內(nèi)容里,MaxHeapSize 是在命令行上配的,-Xmx4096m,這個(gè)java程序可以用到的最大堆內(nèi)存。

VSZ是指已分配的線性空間大小,這個(gè)大小通常并不等于程序?qū)嶋H用到的內(nèi)存大小,產(chǎn)生這個(gè)的可能性很多,比如內(nèi)存映射,共享的動(dòng)態(tài)庫,或者向系統(tǒng)申請(qǐng)了更多的堆,都會(huì)擴(kuò)展線性空間大小,要查看一個(gè)進(jìn)程有哪些內(nèi)存映射,可以使用 pmap 命令來查看:

代碼如下:

[lex@chou ~]$ pmap -x 837

837: java

Address Kbytes RSS Dirty Mode Mapping

0000000040000000 36 4 0 r-x-- java

0000000040108000 8 8 8 rwx-- java

00000000418c9000 13676 13676 13676 rwx-- [ anon ]

00000006fae00000 83968 83968 83968 rwx-- [ anon ]

0000000700000000 527168 451636 451636 rwx-- [ anon ]

00000007202d0000 127040 0 0 ----- [ anon ]

...

...

00007f55ee124000 4 4 0 r-xs- az.png

00007fff017ff000 4 4 0 r-x-- [ anon ]

ffffffffff600000 4 0 0 r-x-- [ anon ]

---------------- ------ ------ ------

total kB 7796020 3037264 3023928

這里可以看到很多anon,這些表示這塊內(nèi)存是由mmap分配的。

RSZ是Resident Set Size,常駐內(nèi)存大小,即進(jìn)程實(shí)際占用的物理內(nèi)存大小, 在現(xiàn)在這個(gè)例子當(dāng)中,RSZ和實(shí)際堆內(nèi)存占用差了2.3G,這2.3G的內(nèi)存組成分別為:

JVM本身需要的內(nèi)存,包括其加載的第三方庫以及這些庫分配的內(nèi)存

NIO的DirectBuffer是分配的native memory

內(nèi)存映射文件,包括JVM加載的一些JAR和第三方庫,以及程序內(nèi)部用到的。上面 pmap 輸出的內(nèi)容里,有一些靜態(tài)文件所占用的大小不在Java的heap里,因此作為一個(gè)Web服務(wù)器,趕緊把靜態(tài)文件從這個(gè)Web服務(wù)器中人移開吧,放到nginx或者CDN里去吧。

JIT, JVM會(huì)將Class編譯成native代碼,這些內(nèi)存也不會(huì)少,如果使用了Spring的AOP,CGLIB會(huì)生成更多的類,JIT的內(nèi)存開銷也會(huì)隨之變大,而且Class本身JVM的GC會(huì)將其放到Perm Generation里去,很難被回收掉,面對(duì)這種情況,應(yīng)該讓JVM使用ConcurrentMarkSweep GC,并啟用這個(gè)GC的相關(guān)參數(shù)允許將不使用的class從Perm Generation中移除, 參數(shù)配置: -XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,如果不需要移除而Perm Generation空間不夠,可以加大一點(diǎn): -X:PermSize=256M -X:MaxPermSize=512M

JNI,一些JNI接口調(diào)用的native庫也會(huì)分配一些內(nèi)存,如果遇到JNI庫的內(nèi)存泄露,可以使用valgrind等內(nèi)存泄露工具來檢測

線程棧,每個(gè)線程都會(huì)有自己的??臻g,如果線程一多,這個(gè)的開銷就很明顯了

jmap/jstack 采樣,頻繁的采樣也會(huì)增加內(nèi)存占用,如果你有服務(wù)器健康監(jiān)控,記得這個(gè)頻率別太高,否則健康監(jiān)控變成致病監(jiān)控了。

關(guān)于JVM的幾個(gè)GC堆和GC的情況,可以用jstat來監(jiān)控,例如監(jiān)控進(jìn)程837每隔1000毫秒刷新一次,輸出20次:

代碼如下:

[lex@chou ~]$ jstat -gcutil 837 1000 20

S0 S1 E O P YGC YGCT FGC FGCT GCT

0.00 80.43 24.62 87.44 98.29 7101 119.652 40 19.719 139.371

0.00 80.43 33.14 87.44 98.29 7101 119.652 40 19.719 139.371

幾個(gè)字段分別含義如下:

S0

年輕代中第一個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比

S1

年輕代中第二個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比

E

年輕代中Eden(伊甸園)已使用的占當(dāng)前容量百分比

O

old代已使用的占當(dāng)前容量百分比

P

perm代已使用的占當(dāng)前容量百分比

YGC

從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中g(shù)c次數(shù)

YGCT

從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中g(shù)c所用時(shí)間(s)

FGC

從應(yīng)用程序啟動(dòng)到采樣時(shí)old代(全gc)gc次數(shù)

FGCT

從應(yīng)用程序啟動(dòng)到采樣時(shí)old代(全gc)gc所用時(shí)間(s)

GCT

從應(yīng)用程序啟動(dòng)到采樣時(shí)gc用的總時(shí)間(s)

結(jié)論

因此如果正常情況下jmap輸出的內(nèi)存占用遠(yuǎn)小于 RSZ,可以不用太擔(dān)心,除非發(fā)生一些嚴(yán)重錯(cuò)誤,比如PermGen空間滿了導(dǎo)致OutOfMemoryError發(fā)生,或者RSZ太高導(dǎo)致引起系統(tǒng)公憤被OOM Killer給干掉,就得注意了,該加內(nèi)存加內(nèi)存,沒錢買內(nèi)存加交換空間,或者按上面列的組成部分逐一排除。

這幾個(gè)內(nèi)存指標(biāo)之間的關(guān)系是:VSZ >> RSZ >> Java程序?qū)嶋H使用的堆大小

更多信息請(qǐng)查看IT技術(shù)專欄

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:JAVA進(jìn)程占用高內(nèi)存原因分析與優(yōu)化方法
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)