jvm Java:如何优化堆分配和垃圾收集?

vwhgwdsa  于 2022-11-07  发布在  Java
关注(0)|答案(3)|浏览(134)

我有一个 Spring 批处理应用程序,它消耗约16 GB内存和75%的CPU(4核X2.5Ghz),有时它抛出内存异常
我想优化堆分配和垃圾收集,并尝试使用以下JVM选项,以便解决内存不足异常
我无法理解其中的一些参数,因为我直接从一篇文章中复制粘贴
JAVA_OPTS="-服务器**-Xmx 20480 m-Xms 512 m**-XX:+使用ConcMarkSweepGC-XX:+使用ParNewGC-XX:+启用CMS类卸载-XX:+启用CMS并行备注-XX:CMS启动占用分数=30 -XX:+CMS增量模式-XX:+CMS增量调整-XX:并行CMS线程数=2 -XX:+使用CMS完整收集时压缩-XX:+禁用显式GC-XX:最大堆空闲比率=70 -XX:最小堆空闲比率=40-XX:最大保留阈值=0 -XX:新大小= 450 m-XX:最大新大小= 650 m”
它真的会优化堆分配和垃圾收集并解决内存不足异常吗?

vhmi4jdf

vhmi4jdf1#

首先,当进程抛出OOM错误时,您需要对进程进行堆转储。您可以通过添加-XX:+HeapDumpOnOutOfMemoryError JVM选项来完成此操作。在进行堆转储后,尝试使用以下任何工具来分析堆转储。找到内存中正在增长的对象,然后对其进行优化。堆转储分析工具包括:

  1. Eclipse Memory Analyzer
  2. Heap Hero
  3. jxray
c9qzyr3d

c9qzyr3d2#

当Java堆上没有足够的空间来分配对象时,或者如果Java进程将其98%以上的时间用于垃圾收集,并且如果它恢复的堆不到2%,并且到目前为止已经执行了最后5个垃圾收集周期,则通常会引发此错误。
我会首先使用Java分析器来确定哪些方法在堆上分配了大量对象,并确保它们在不再需要之后不再被引用。如果这不能解决问题,并且我已经确认我需要所有的对象,另一个选择是增加程序的最大堆大小。

hwamh0ep

hwamh0ep3#

  • 当您使用太多的'String'对象或一次又一次地更新这些字串时,也可能会发生这种情况。
  • 字符串存储在一个散列字符串池中,该池位于堆空间中。当您操作一个字符串时,会形成一个新的字符串并将其存储在另一个池(散列池)中,但原始字符串不会被删除,直到垃圾收集器删除它。
  • 如果我们使用StringBuilder或StringBuffer(两者都是可变的,不像字符串),空间会得到更好的利用。

阅读更多关于字符串不变性的内容,以及当您需要执行大量字符串操作时,为什么首选stringbuilder。
Java Why strings are immutable in java?中的字符串生成器-字符串缓冲区

相关问题