JVM使用的内存超过了最大堆内存

8

我们的JVM出现了问题,它使用的内存超过了最大值-Xmx。

我们使用的是-Xmx2048,但目前它正在使用17GB的操作系统内存。

我知道JVM可以使用比最大堆更多的内存,但我们的JVM使用了15GB以上的内存,这似乎很疯狂。

顶部转储看起来像这样:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                          
30477 root      20   0 22.683g 0.017t  18536 S   0.7 29.1  27:43.44 java -Xmx2048M -Xms1024M -XX:MaxPermSize=256M -XX:ReservedCodeCacheSize=128M  ....

(注意它使用的是0.017TB或17GB)。

我尝试使用jmap进行调试:

sudo jmap -J-d64 -heap 30477

Attaching to process ID 30477, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.75-b04

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

Heap Configuration:
   MinHeapFreeRatio = 0
   MaxHeapFreeRatio = 100
   MaxHeapSize      = 2147483648 (2048.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 268435456 (256.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 316145664 (301.5MB)
   used     = 150828136 (143.8409194946289MB)
   free     = 165317528 (157.6590805053711MB)
   47.708431009827166% used
From Space:
   capacity = 20447232 (19.5MB)
   used     = 3406624 (3.248809814453125MB)
   free     = 17040608 (16.251190185546875MB)
   16.660563151041668% used
To Space:
   capacity = 21495808 (20.5MB)
   used     = 0 (0.0MB)
   free     = 21495808 (20.5MB)
   0.0% used
PS Old Generation
   capacity = 716177408 (683.0MB)
   used     = 516302952 (492.3848648071289MB)
   free     = 199874456 (190.6151351928711MB)
   72.09148825873044% used
PS Perm Generation
   capacity = 56098816 (53.5MB)
   used     = 55842840 (53.255882263183594MB)
   free     = 255976 (0.24411773681640625MB)
   99.54370516482915% used

15065 interned Strings occupying 1516808 bytes.

And also...

sudo jmap -J-d64 -permstat 30477

Attaching to process ID 30477, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.75-b04
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness...liveness analysis may be inaccurate ...
class_loader    classes bytes   parent_loader   alive?  type

<bootstrap> 1908    11793728      null      live    <internal>
0x0000000780b97590  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b99b28  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b96cb0  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113ca0  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b97c90  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114458  1   3048      null      dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b892b0  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b989a8  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780019cf0  7731    44085000    0x0000000780019d40  live    sun/misc/Launcher$AppClassLoader@0x0000000770239a20
0x0000000780113f10  1   3152    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780aa8918  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114008  1   3040    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b7a8b8  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780d236d0  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780019d40  207 1327296   null      live    sun/misc/Launcher$ExtClassLoader@0x00000007701eb8b8
0x0000000780113e28  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x00000007801140b0  1   3064    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x000000078dc814f8  1   3024      null      dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b8abf8  1   3208    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b990a8  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114130  1   1904    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b98010  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x00000007801141b0  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113620  27  86320   0x0000000780019cf0  live    org/apache/tapestry5/internal/plastic/PlasticClassLoader@0x000000077181b058
0x0000000780114418  1   3064    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b98d28  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b89270  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113ed0  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b97910  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b997a8  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b96930  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780d36d38  1   3024    0x0000000780019d40  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b99ea8  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780bddff8  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780a63ca0  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114048  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113fc8  1   3024      null      dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113de8  1   3072    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b7afb8  1   3040      null      dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113e68  1   1904    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b7ac38  1   1880      null      dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780113d58  1   3064    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x00000007801140f0  1   3280    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b98628  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x000000078088f900  0   0   0x0000000780019cf0  dead    java/util/ResourceBundle$RBClassLoader@0x00000007709cda40
0x0000000780b99428  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780d28ba0  1   3024    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b97030  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114170  1   3064    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x00000007801143d8  1   3048    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780114240  1   1880    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770
0x0000000780b8af60  1   3104    0x0000000780019cf0  dead    sun/reflect/DelegatingClassLoader@0x0000000770059770

total = 53  9921    57418080        N/A     alive=4, dead=49        N/A    

该应用是一个Play应用程序,我知道它在类加载器方面做了一些奇怪的事情,但我认为-permstat应该可以解决这个问题,所以我很困惑。 有什么想法吗? 约翰

2
应用程序或其任何嵌入式库是否将文件映射到内存中?例如,Cassandra 就以此而闻名。 - Chris K
2
除了Chris的观点,你的应用程序是否通过JNI调用任何本地代码? - Amir Afghani
内存映射文件不是问题,因为它们只分配地址空间,而不是 RAM。因此,这个指示可能不是什么需要担心的事情。 - Marko Topolnik
1
在这种情况下,其他页面可能会被删除,这不一定是一个问题...也许是,但也可能不是。在这种情况下,我同意Marko的观点,由于内存映射文件导致非常高的内存使用率的进程通常不是问题。但正如你所暗示的那样,这并不是明确的,因为如果处于高变异率下,则可能成为问题。目前,OP还没有确认我们是否正在查看内存映射问题,所以让我们等待看看这是否是一个误导。 - Chris K
关于JNI代码...肯定不是我们的代码。在Play库中可能存在,尽管这对我们来说是一个新问题。我尝试使用pmap,它报告说映射了22341732K...不确定如何准确解释这个。需要一份转储文件吗? - John
显示剩余11条评论
2个回答

6
请注意,堆区(由Xmx界定)仅是JVM进程的一部分。
基本上,JVM占用的内存是以下内容的总和:
- 堆(由Xmx界定) - PermGen(在Java 7及以下版本中,由MaxPermSize界定) - 线程栈:每个线程大约512KB至1024KB(取决于JVM和操作系统) - 本地缓冲区 - JVM代码 - 通过JNI访问的本地数据/代码
可能还有其他一些内容,你可以通过搜索找到它们:)
因此,您必须检查所有这些区域以确保哪些正在消耗内存。
我敢打赌,您可能存在简单的线程泄漏 - 成千上万的线程可能会占用大量内存(如我所说,假设每个线程占用1MB,10000个线程对应10GB的内存)。 您可以简单地进行线程转储(jstack -l > dumpfile.txt)以查看是否存在问题。
当然,也可能是使用本地缓冲区或JNI的外部库,但这种可能性较小。

谢谢你的回复。正如我所说,堆仅限于2GB——这已经通过jmap dump得到了确认。按照建议进行线程转储 - 只有大约50个线程(远低于正常使用)。从jmap dump中看来,PermGen似乎没问题(参见上文)。我会调查本地缓冲区问题。 - John

4
所以我们解决了这个问题,原因只是开发人员的错误。感谢所有提供帮助建议的人。
我还是回答一下,以便将来能帮到任何人。
问题很简单,就是没有关闭使用Class.getInputAsStream()读取的资源打开的流。
混淆产生的原因是JVM堆使用率微不足道,但每个未关闭的流留下了一些分配但没有释放的本机代码。
由于没有文件句柄泄漏(可能是因为我们每次都从主JAR文件中读取,它重复使用相同的句柄),并且JVM堆使用率很小,直到实际进行堆转储时我们才发现问题。
无论如何,故事的寓意是不要犯我所犯的错误,即假设JVM堆使用率很低,则没有必要查看堆转储,因为在这种情况下,看到仍然分配了数千个对象给了我们一个线索。
谢谢大家!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接