《被kill問題之1:進程物理內存遠大於Xmx的問題分析》
《被kill問題之2:Docker環境下Java應用的JVM設置(容器中的JVM資源該如何被安全的限制)》
問題描述
最近經常被問到一個問題,”為什么我們系統進程占用的物理內存(Res/Rss)會遠遠大於設置的Xmx值”,比如Xmx設置1.7G,但是top看到的Res的值卻達到了3.0G,隨着進程的運行,Res的值還在遞增,直到達到某個值,被OS當做bad process直接被kill掉了。
top - 16:57:47 up 73 days, 4:12, 8 users, load average: 6.78, 9.68, 13.31 Tasks: 130 total, 1 running, 123 sleeping, 6 stopped, 0 zombie Cpu(s): 89.9%us, 5.6%sy, 0.0%ni, 2.0%id, 0.7%wa, 0.7%hi, 1.2%si, 0.0%st ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 22753 admin 20 0 4252m 3.0g 17m S 192.8 52.7 151:47.59 /opt/taobao/java/bin/java -server -Xms1700m -Xmx1700m -Xmn680m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseStringCache -XX:+ 40 root 20 0 0 0 0 D 0.3 0.0 5:53.07 [kswapd0]
物理內存大於Xmx可能嗎
先說下Xmx,這個vm配置只包括我們熟悉的新生代和老生代的最大值,不包括持久代,也不包括CodeCache,還有我們常聽說的堆外內存從名字上一看也知道沒有包括在內,當然還有其他內存也不會算在內等,因此理論上我們看到物理內存大於Xmx也是可能的,不過超過太多估計就可能有問題了。
物理內存和虛擬內存間的映射關系
我們知道os在內存上面的設計是花了心思的,為了讓資源得到最大合理利用,在物理內存之上搞一層虛擬地址,同一台機器上每個進程可訪問的虛擬地址空間大小都是一樣的,為了屏蔽掉復雜的到物理內存的映射,該工作os直接做了,當需要物理內存的時候,當前虛擬地址又沒有映射到物理內存上的時候,就會發生缺頁中斷,由內核去為之准備一塊物理內存,所以即使我們分配了一塊1G的虛擬內存,物理內存上不一定有一塊1G的空間與之對應,那到底這塊虛擬內存塊到底映射了多少物理內存呢,這個我們在linux下可以通過 /proc/<pid>/smaps
這個文件看到,其中的Size表示虛擬內存大小,而Rss表示的是物理內存,所以從這層意義上來說和虛擬內存塊對應的物理內存塊不應該超過此虛擬內存塊的空間范圍
8dc00000-100000000 rwxp 00000000 00:00 0 Size: 1871872 kB Rss: 1798444 kB Pss: 1798444 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 1798444 kB Referenced: 1798392 kB Anonymous: 1798444 kB AnonHugePages: 0 kB Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB
此次為了排查這個問題,我特地寫了個簡單的分析工具來分析這個問題,將連續的虛擬內存塊合並做統計,一般來說連續分配的內存塊還是有一定關系的,當然也不能完全肯定這種關系,得到的效果大致如下:
from->to vs rss rss_percentage(rss/total_rss) merge_block_count
0x8dc00000->0x30c9a20000 1871872 1487480 53.77% 1 0x7faf7a4c5000->0x7fffa7dd9000 1069464 735996 26.60% 440 0x7faf50c75000->0x7faf6c02a000 445996 226860 8.20% 418 0x7faf6c027000->0x7faf78010000 196452 140640 5.08% 492 0x418e8000->0x100000000 90968 90904 3.29% 1 0x7faf48000000->0x7faf50c78000 131072 35120 1.27% 4 0x7faf28000000->0x7faf3905e000 196608 20708 0.75% 6 0x7faf38000000->0x7faf4ad83000 196608 17036 0.62% 6 0x7faf78009000->0x7faf7a4c6000 37612 10440 0.38% 465 0x30c9e00000->0x30ca202000 3656 716 0.03% 5 0x7faf20000000->0x7faf289c7000 65536 132 0.00% 2 0x30c9a00000->0x30c9c20000 128 108 0.00% 1 0x30ca600000->0x30cae83000 2164 76 0.00% 5 0x30cbe00000->0x30cca16000 2152 68 0.00% 5 0x7fffa7dc3000->0x7fffa7e00000 92 48 0.00% 1 0x30cca00000->0x7faf21dba000 2148 32 0.00% 5 0x30cb200000->0x30cbe16000 2080 28 0.00% 4 0x30cae00000->0x30cb207000 2576 20 0.00% 4 0x30ca200000->0x30ca617000 2064 16 0.00% 4 0x40000000->0x4010a000 36 12 0.00% 2 0x30c9c1f000->0x30c9f89000 12 12 0.00% 3 0x40108000->0x471be000 8 8 0.00% 1 0x7fffa7dff000->0x0 4 4 0.00% 0
當然這只是一個簡單的分析,如果更有價值需要我們挖掘更多的點出來,比如每個內存塊是屬於哪塊memory pool,到底是什么地方分配的等,不過需要jvm支持( 注:上面的第一條,其實就是new+old+perm對應的虛擬內存及其物理內存映射情況
)。
進程滿足什么條件會被os因為oom而被kill
當一個進程無故消失的時候,我們一般看 /var/log/message
里是否有 Out of memory: Kill process
關鍵字(如果是java進程我們先看是否有crash日志),如果有就說明是被os因為oom而被kill了:
Aug 19 08:32:38 mybank-ant kernel: : [6176841.238016] java invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238022] java cpuset=/ mems_allowed=0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238024] Pid: 25371, comm: java Not tainted 2.6.32-220.23.2.ali878.el6.x86_64 #1 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238026] Call Trace: Aug 19 08:32:38 mybank-ant kernel: : [6176841.238039] [<ffffffff810c35e1>] ? cpuset_print_task_mems_allowed+0x91/0xb0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238068] [<ffffffff81114d70>] ? dump_header+0x90/0x1b0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238074] [<ffffffff810e1b2e>] ? __delayacct_freepages_end+0x2e/0x30 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238079] [<ffffffff81213ffc>] ? security_real_capable_noaudit+0x3c/0x70 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238082] [<ffffffff811151fa>] ? oom_kill_process+0x8a/0x2c0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238084] [<ffffffff81115131>] ? select_bad_process+0xe1/0x120 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238087] [<ffffffff81115650>] ? out_of_memory+0x220/0x3c0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238093] [<ffffffff81125929>] ? __alloc_pages_nodemask+0x899/0x930 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238099] [<ffffffff81159b6a>] ? alloc_pages_current+0xaa/0x110 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238102] [<ffffffff81111ea7>] ? __page_cache_alloc+0x87/0x90 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238105] [<ffffffff81127f4b>] ? __do_page_cache_readahead+0xdb/0x270 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238108] [<ffffffff81128101>] ? ra_submit+0x21/0x30 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238110] [<ffffffff81113e17>] ? filemap_fault+0x5b7/0x600 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238113] [<ffffffff8113ca64>] ? __do_fault+0x54/0x510 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238116] [<ffffffff811140a0>] ? __generic_file_aio_write+0x240/0x470 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238118] [<ffffffff8113d017>] ? handle_pte_fault+0xf7/0xb50 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238121] [<ffffffff8111438e>] ? generic_file_aio_write+0xbe/0xe0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238133] [<ffffffffa008a171>] ? ext4_file_write+0x61/0x1e0 [ext4] Aug 19 08:32:38 mybank-ant kernel: : [6176841.238135] [<ffffffff8113dc54>] ? handle_mm_fault+0x1e4/0x2b0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238138] [<ffffffff81177c7a>] ? do_sync_write+0xfa/0x140 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238143] [<ffffffff81042c69>] ? __do_page_fault+0x139/0x480 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238147] [<ffffffff8118ad22>] ? vfs_ioctl+0x22/0xa0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238151] [<ffffffff814e4f8e>] ? do_page_fault+0x3e/0xa0 Aug 19 08:32:38 mybank-ant kernel: : [6176841.238154] [<ffffffff814e2345>] ? page_fault+0x25/0x30 ... Aug 19 08:32:38 mybank-ant kernel: : [6176841.247969] [24673] 1801 24673 1280126 926068 1 0 0 java Aug 19 08:32:38 mybank-ant kernel: : [6176841.247971] [25084] 1801 25084 3756