分析内存问题

描述

环境
Experience Manager

问题/症状
java应用程序运行速度较慢,最终内存不足,或者在日志或控制台输出中看到错误 OutOfMemoryError: Java heap space 或 OutOfMemoryError: gc overhead limit exceeded.

分辨率

原因

此类问题可能有很多原因。

一个可能的原因是,在我们的示例中,Java应用程序是从使用Java默认堆内存设置的命令行启动的。 这意味着 jvm 参数 -Xmx 未指定。 CRX 或 CQ 至少需要分配 256 MB 的堆才能运行。 如果这是问题所在,则从命令行开始,请确保设置了堆内存设置。 示例:

java -Xmx512m -jar *.jar

如果不是这种情况,那么您的应用程序可能会保留太多对象而没有为垃圾收集释放它们。这称为内存泄漏,请参阅此处了解更多信息。请参阅下面有关如何分析 Java 应用程序中的内存问题的部分。
创建堆转储
自动生成堆转储

要在内存不足时自动创建堆转储,可添加jvm参数 -XX:+HeapDumpOnOutOfMemoryError ,以在应用程序引发OutOfMemoryError时自动生成堆转储。 例如,

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

这会生成堆转储文件(java_...hprof)。 生成堆转储后,该进程可以继续运行。通常,一个堆转储文件就足以分析问题。

注意:如果您正在使用 crx-quickstart/server/start 脚本来启动 CRX 实例,则您可以添加 -XX:+HeapDumpOnOutOfMemoryErrorCQ_JVM_OPTS 变量(确保变量也未注释)。例如:

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

添加此参数并重新启动 CRX 实例后,验证是否设置了新的 jvm 选项。 从命令行运行 ps -ef | grep java。 然后检查您是否看到 -XX:+HeapDumpOnOutOfMemoryError 作为CRX java进程的参数。

如果由于磁盘空间限制需要指定不同的目录来生成堆转储,则可以添加 -XX:HeapDumpPath=/path/to/generate/heapdump 参数告诉 jvm 文件的放置位置。

请参阅此处,了解有关调试相关 jvm 参数的引用。

手动生成堆转储

Sun/OracleJVM

要手动生成堆转储,请运行此命令(jmap 和 jps 可见于 jdk 主目录下的 bin 文件夹):

  1. 查找要为其生成堆转储的java进程的pid。

    • 在Unix或Linux中,可以通过 ps -ef | grep java 或 jps -l
    • 在Windows中,可通过打开任务管理器来完成此操作,请按 Ctrl+Shift+Esc 然后转到 查看 = 选择列 = PID(进程标识符) 或 jps -l
  2. 运行下面的 jmap 命令,使用您要生成堆转储文件的位置替换 /path/to/generate/heapdumpfile.hprof,然后使用您在上一步中查找的 pid 替换 1234

    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

您首先必须更改有关转储代理的默认 JVM 设置,以便在用户信号上生成正确的转储。 有几种转储,但您通常需要完整的转储系统转储进行彻底的内存分析。添加以下参数:

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

当JVM从操作系统收到SIGQUIT(Linux、AIX®、z/OS®和i5/OS™)或SIGBREAK(Windows)信号时,会发生此“用户”事件。

有关详细信息,请在此处参阅供应商的文档。

警告: 堆转储文件较大,并且在磁盘上的大小可以与最大堆 — Xmx jvm参数配置相同。 确保您有足够的磁盘空间分配给生成转储文件的目录。

分析堆转储

分析堆转储的一个好工具是EclipseMAT(Eclipse Memory Analyzer): http://www.eclipse.org/mat/

此工具无法分析 IBM JVM 生成的转储。 对于以上问题,有几种可能性。IBM HeapAnalyzer 将适用于 PHD 或经典格式的堆转储。

要获取完整的系统转储分析,请使用 IBM支持助手工作台,使用 IBM Monitoring and Diagnostic Tools for Java - Memory Analyzer 1.2版 安装在顶部。

堆直方图

堆直方图是对每个Java类使用的实时对象数和内存的简单测量。 遗憾的是,根据Java的安装,所需的工具可能不可用,或者可能不总能正常工作。 要创建堆直方图,您首先需要Java进程的进程ID。 要得到该 ID,请运行 ps 或(如果可用),运行:

jps -l

此Java工具获取所有正在运行的Java进程的进程ID。 示例:

327
3332 sun.tools.jps.Jps
3313 crx-quickstart-....jar

现在,请运行以下命令:

jmap -histo 3313

该列表按所需的总内存排序(简略:不包括引用的对象)。输出的前 20 行是最有趣的。 输出示例:

JVM version is 1.5.0_20-141
Iterating over heap. This may take a while...
Warning: skipping invalid TLAB for thread t@62211
Warning: skipping invalid TLAB for thread t@62467
...
SizeCountClass description
-------------------------------------------------------
1059290412916byte
1028584075255* ConstMethodKlass
628317658388char
604230414928int
4995752116201* SymbolKlass
422089675255* MethodKlass
41965126969* ConstantPoolKlass
29285606969* InstanceKlassKlass
26310086066* ConstantPoolCacheKlass
2395872149742org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId
14760087003java.util.HashMap$Entry
139612858172java.lang.String
107023244593java.util.HashMap$Entry
75398410036short
73546454org.apache.jackrabbit.core.query.lucene.DocId
7201927502java.lang.Class
64070413348com.day.crx.persistence.tar.index.IndexEntry
...

其他信息

为了帮助分析问题,我们还需要了解以下信息:

  • CRX 或 CQ 版本,包括所有已安装修补程序版本号的列表。
  • 操作系统版本、JVM 供应商和版本。

引用

http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/memleaks.html
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

在此页面上