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

Java: How to optimize the Heap allocation & Garbage collection?

我有一个 spring 批处理应用程序,它消耗 ~16GB 内存和 CPU(4core X2.5Ghz) 的 75%,有时它 抛出内存异常.

我想优化堆分配和垃圾收集并尝试使用以下 JVM 选项来解决 内存不足异常

有些参数看不懂,因为我直接从一篇文章中复制粘贴

JAVA_OPTS="-server -Xmx20480m -Xms512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=30 -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:ParallelCMSThreads=2 -XX:+UseCMSCompactAtFullCollection -XX:+DisableExplicitGC -XX:MaxHeapFreeRatio=70 -XX:MinHeapFreeRatio=40 -XX:MaxTenuringThreshold=0 -XX:NewSize=450m -XX:MaxNewSize=650m"

它真的会优化堆分配和垃圾收集并解决内存不足异常吗?

如果 space 不足以在 Java 堆上分配对象,或者如果 Java 进程花费超过 98% 的时间在做垃圾收集,如果它正在恢复不到 2% 的堆并且到目前为止一直在执行最后 5 个垃圾收集周期。

我会首先使用 Java 分析器来确定哪些方法正在堆上分配大量对象,并确保在不需要它们后不再引用它们。如果这不能解决问题并且我已经确认我需要所有对象,另一个选择是增加程序的最大堆大小。

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

  1. Eclipse Memory Analyzer
  2. Heap Hero
  3. jxray
  • 当您使用太多 'String' 对象或一次又一次地更新这些字符串时,也可能会发生这种情况。
  • 字符串存储在散列字符串池中,该池位于堆 space 中。当您操作一个字符串时,会形成一个新的字符串并将其存储在不同的池(散列池)中,但在垃圾收集器执行此操作之前不会删除原始字符串。
  • 如果我们使用 StringBuilder 或 StringBuffer(两者都是可变的,不像字符串),space 更好地利用。

阅读更多关于字符串不变性的信息,以及为什么当您需要执行大量字符串操作时应该首选 stringbuilder。

StringBuilder-StringBuffer-Strings in java Why strings are immutable in java?