Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 32位JVM提交>;3G虚拟内存_Java_Linux_Memory Management_Jvm_32bit 64bit - Fatal编程技术网

Java 32位JVM提交>;3G虚拟内存

Java 32位JVM提交>;3G虚拟内存,java,linux,memory-management,jvm,32bit-64bit,Java,Linux,Memory Management,Jvm,32bit 64bit,我们有一个在64位RHEL5下运行的32位JVM,它位于一个内存充足(32G)的盒子上。出于不同的原因,此进程需要相当大的托管堆和永久空间——目前,它使用以下VM参数运行: -Xmx2200M-XX:MaxPermSize=128M-XX:+CMSClassUnloadingEnabled 我最近开始看到JVM崩溃,因为它似乎耗尽了本机内存(它无法创建本机线程,或者无法分配本机内存,等等)。这些崩溃与托管堆的状态没有(直接)关系,因为当这些崩溃发生时,托管堆已满约50-70%。 我知道为托管进

我们有一个在64位RHEL5下运行的32位JVM,它位于一个内存充足(32G)的盒子上。出于不同的原因,此进程需要相当大的托管堆和永久空间——目前,它使用以下VM参数运行:

-Xmx2200M-XX:MaxPermSize=128M-XX:+CMSClassUnloadingEnabled

我最近开始看到JVM崩溃,因为它似乎耗尽了本机内存(它无法创建本机线程,或者无法分配本机内存,等等)。这些崩溃与托管堆的状态没有(直接)关系,因为当这些崩溃发生时,托管堆已满约50-70%。 我知道为托管进程保留的内存接近2.5G,这给JVM本身留下的内存不超过0.5G,但是 -我不明白为什么0.5对于JVM是不够的,即使有持续的GCing -真正的问题是:当我使用jconsole连接到进程时,它会说(当前)

这比3G还多。我可以想象,出于某种原因,JVM认为它 3211180千字节(3.06G)的内存不足,但当它试图通过3G时,内存分配失败

有什么想法吗 a) 为什么会发生这种情况 b) 如何避免这种情况

谢谢。
Mate

在一个典型的虚拟机中,有很多开销没有计入虚拟机记帐中,因为它基本上是被进程的本机元素窃取的,例如映射到。因此,用于执行系统库本机级别代码的文件不计入基本虚拟机记帐中。您的典型共享库映射到内存的顶部GB,因此如果您尝试将内存分配到该区域,您将被拒绝,因为它将与共享库的内存区域一起溢出-大多数操作系统上的内存分配是通过一个简单的条来执行的,当您请求更多内存时,该条会弹出。当您请求内存时,如果该条与其他用途冲突,那么它就会失败。接下来的大部分细节都与此有关

您需要避免在32位进程中需要如此多的内存。这是根本性的挑战。获得一个64位的虚拟机是很简单的,它允许您使用比其他方式更大的内存,在这种情况下它只是简单地可用

如果您使用的是32位进程,则很可能会遇到32位进程的有效地址空间限制。对于windows,这是大约3GB的最大值-超过此值的任何内容都将保留给I/O空间和内核。您可以改变这一点,但它倾向于破坏为32位操作系统设计的应用程序/驱动程序

对于Linux,每个进程都会有大约3GB的可用可寻址RAM,其余的都会被内核之类的东西消耗掉,并映射到共享库中。这个限制被称为“地址空间限制”,我认为它是可以调整的

如何避免呢?嗯,在大多数情况下,您不能,这是32位地址空间的物理限制,并且需要使内核/IO与32位操作系统的进程位于相同的地址空间


使用64位操作系统,您可以(大部分)使用所有64位地址空间,这远远超出了您需要使用的范围。

启动JVM时,它会立即为其分配最大大小。内存的使用量并不重要。您的应用程序可以处理大约3 GB的地址,其中大约2.3 GB已分配给heap和perm gen。其余的可用于共享库(通常约200 MB)和线程堆栈


在解决方案相对简单(使用64位JVM)的情况下,担心为什么不能使用完整的3 GB地址并不是很有用。我假设您没有任何共享库,而这些库只能使用32位。但是,如果您有额外的共享库,它们可以轻松地使用100 MB。

在64位Windows下,32位进程可以使用完整的4GB地址空间-操作系统不再需要在32位地址空间中保留空间,因为它可以使用64位地址空间。好的,请注意,这是标记为linux的,我仍然想象它以类似的方式工作。如果是,那么我仍然不明白它为什么会耗尽本机内存/如果“本机内存”的意思是“物理内存”,那么它可能不是-如果您有一个交换分区,那么操作系统将根据需要将物理内存分页到磁盘上。更可能的情况是虚拟地址空间是碎片化的,即,即使虚拟地址空间中有可用空间,可用空间也会被分成许多小块,其中最大的小块太小,无法进行所需的分配。是的,很可能是地址空间用完了。即使没有碎片,当您有3.5G JVM堆时,0.5G的机器堆也不是很多。对于很多小对象,单是GC就可以承受这么多,更不用说线程、类等的非GCed部分了。嗨,谢谢——我想我理解内存限制和地址空间限制的含义。我的主要问题是,我不明白JVM为什么会耗尽本机内存——我认为0.5G应该足以为GC等提供临时空间。我们当然可以转移到64位JVM,但最好知道是什么导致JVM使用700M额外空间,但是没有好的工具来调试JVM本身。很有可能它不会耗尽“实际内存”,而是耗尽了可用内存。您应该查看从/proc/pid/maps生成的内存映射,它说明了应用程序的内存利用率。内存的使用不仅仅是您声明的基数,您还拥有JIT内存、保护页,映射到共享对象中。如果在一个进程中有350MB的内存变化,那么就没有足够的内存池。这是长期服务中经常出现的问题。嗨,谢谢——我一般不相信
Committed virtual memory: 
3,211,180 kbytes