它可能导致的默认Java堆大小和内存问题

时间:2018-02-27 18:56:00

标签: java java-8 garbage-collection jvm heap-memory

我有一个应用程序,其后端基于Java 8构建。最近,由于OOM,我已经看到应用程序自行重启。我通过查看Docker Container的退出状态来了解它是因为OOM。没有为系统配置XmxXms值,因此它应该使用默认堆大小,如果我的服务器有4 GB内存应该是大约512 MB(我读取一些SO答案,即deafult heap max size是存在的内存的1/8)。设置XmsXmx值后,我的应用现在无需重启即可正常运行。在设置XmxXms值之前,我还尝试将服务器中的内存增加到7场演出,但它也没有帮助。我想知道的是,当应用程序有足够的可用内存时,系统如何运行OOM 如果应用程序的内存需求增加,默认堆大小是否会自行扩展?如果内存满了,为什么GC没有被触发?

3 个答案:

答案 0 :(得分:3)

  

如果内存要求,默认堆大小是否会自行扩展   应用增加了吗?

是的,但最多只能达到-Xmx中的值(或JVM选择的该值的默认值)。

  

如果内存满了,为什么GC没有被触发?

GC被触发,但它无法收集任何垃圾。堆中的所有东西都是非垃圾。

答案 1 :(得分:2)

  “当有足够的记忆时,系统如何进行OOM   可用于该应用程序。“

这里有两个可能的问题:

  1. 您还没有为应用程序的内存需求配置足够的内存,那么您可以共享配置的值吗?

  2. 应用程序导致内存泄漏问题,因此您应该记住这一点

  3. 来源:http://blog.sysco.no/memory/leak/memory-leak/

      

    Java的一个主要优点是使用垃圾收集器   这让程序员忘记了内存管理。那是   不是你必须分配的C ++等语言的情况   自代码以来的可用内存。根据我在一家大公司的经历,我看到了   内存泄漏问题多次导致不可用或   许多应用程序的性能不佳。

         

    此外,内存泄漏属于一类被称为的情境   软件老化问题。软件老化定义了损失   随着时间的推移,表现逐渐积累   小问题。这类问题中的其他术语是   复兴过程。例如,当复兴时发生   系统必须重新启动才能释放累积的内存   一段时间后的Java虚拟机(JVM)进程(COTRONEO,   D,et al。,2015)。

    基本上,JVM上的垃圾收集器使用一种机制来重用对象的空间,这些机制没有来自根集的任何引用,因此当源代码或配置中存在一个问题时,对象始终保持引用,很少应用程序将逐渐填满堆,直到达到其极限。

    例如,在下图中,只会收集图中的无法访问的对象,所有可访问的对象(即使是由错误或错误配置生成的对象)将保留在堆中

    enter image description here

    来源http://blog.sysco.no/files/guides/JVMGarbageCollectionV1.1.pdf

      

    “如果内存要求,默认堆大小是否会自行扩展   应用程序的增加?“

    答案不是,当tyour应用程序填满整个新一代时,JVM将执行一个次要的GC来释放新一代的对象,那些幸存者会被移入幸存者空间一段时间,直到他们达到某个年龄。当它们(幸存者空间中的物体)足够成熟并且仍然存活时,这些物体被提升到老一代,当旧一代充满时,执行完整的GC。因此,因为您的应用程序似乎在某个时刻保留引用(内存泄漏),整个堆将填充活动对象,因此JVM无法释放它们,并且它没有标志来增加内存的情况像这样。

      

    “如果内存满了,为什么GC没有被触发?”

    在这种情况下,我有一个问题,您如何知道GC是否被触发?要调整垃圾收集过程,您必须对此进行测量,以便您可以尝试使用这些标志来获取有关GC执行的信息。

    -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -Xloggc:/home/user666/gc.log

    此外,您可以使用这个漂亮的网络来分析日志文件

    http://gceasy.io/

    Las但并非最不重要,你可以使用这些标志

    -XX:+ HeapDumpOnOutOfMemoryError -XX:HeapDumpPath = / some / where / your / machine

    使用这些标志,您将生成堆转储,可以使用Memory Analyzer Tool(MAT:https://www.eclipse.org/mat/downloads.php)进行分析,以确定应用程序是否存在内存泄漏。

答案 2 :(得分:1)

默认的最大堆大小是主内存的1/4。这假设机器不专用于这一个过程。如果是,您可能希望增加最大堆大小。

注意:堆大小只是堆的大小,它只是JVM使用的一个内存区域。 总内存消耗量。 JVM需要多少额外内存取决于它正在做什么。

初始大小可以增长到最大值。最大的大小不会增长,它是您希望进程死的堆的大小而不是使用的大小。

如果没有更多信息,我会尝试在4 GB计算机上运行3 GB堆,如果它正在运行并看看它是如何运行的。您可以在top

中监控进程尝试使用的虚拟内存量

注意:并非所有OutOfMemoryError都相同,您需要阅读错误消息以确定问题的实际原因。例如你可能已经用完了线程,perm gen / metaspace或其他一些低级内存问题。