Java 進程占用 VIRT 虛擬內存超高的問題研究


一、現象說明

最近發現線上機器java 7(openjdk)進程的 VIRT 虛擬內存使用達到了 50G+,如下所示:

PID      USER  PR NI     VIRT  RES    SHR     S   %CPU   %MEM    TIME+    COMMAND 
3130    tomcat  20  0    9128m  1.4g   6544    S    1.3   9.0    84:14.67  java 
31480   tomcat  20  0    7244m  983m   5528    S    0.3   6.2     34:36.95  java 
22142   tomcat  20  0    6787m   537m   13m     S    0.7   3.4     6:26.70   java 
22097   tomcat  20  0    7049m   515m   11m    S     0.3  3.2     4:52.39   java 
1975    root    20  0    600m    10m    1560   S     0.0  0.1     2:50.42   salt-minion

根據現象猜測:

1. 可能出現內存不足,使用了較多的swap內存;

2. java jdk的版本導致;

3. 由於是虛擬機可能出現物理主機內存不足,導致虛擬機偽內存資源;

二、問題排查

2.1 不管用 xms

首先第一想到的當然使用 java 的-Xmx去限制堆的使用。然而通過top查看,其實並沒有使用多少物理內存。

2.2 通過vmstate查看分析

 

[root@busys-12173 ~]# vmstat -a -S M
procs      -----------memory----------    ---swap--     -----io----    --system--     -----cpu-----
r  b    swpd   free   inact  active     si   so        bi     bo       in     cs       us sy id  wa st
0 0     81     1604   340    3381       0    0         1       1       6      15       0   0 100  0  0

 

從上面的信息,可以看出來其實資源使用實際很少;

2.3 排查虛擬機資源是否消耗

經過查看vmware,發現上面的虛擬機資源使用並無異常。

三、確定問題原因

經過查閱資料,偶然間發現,這屬於一個正常的現象,為什么正常呢?請看下面分析。

glibc 在版本 2.10 引入的 arena 新功能導致。CentOS 6/7 的 glibc 大都是 2.12/ 2.17 了,所以都會有這個問題。這個功能對每個線程都分配一個分配一個本地arena來加速多線程的執行。Java 程序由於自己維護堆的使用,導致調用 glibc 去管理內存的次數較少。更糟的是 Java 8 開始使用 metaspace 原空間取代永久代,而元空間是存放在操作系統本地內存中,那線程一多,每個線程都要使用一點元空間,每個線程都分配一個 arena,每個都64MB,就會導致巨大的虛擬地址被分配。

總結如下:

  • VIRT高是因為分配了太多地址空間導致。
  • 一般來說不用太在意VIRT太高,因為你有更多的空間可以使用。
  • 如果你實在需要控制VIRT的使用,設置環境變量MALLOC_ARENA_MAX,例如hadoop推薦值為4,因為YARN使用VIRT值監控資源使用。

參考鏈接:https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM