分析内存问题
了解如何识别Java应用程序内存问题的原因。 您可以自动手动生成栈转储和栈直方图,以识别原因。
描述 description
环境
Experience Manager
问题/症状
JAVA应用程序运行速度较慢并最终耗尽内存,或者您在日志或控制台输出OutOfMemoryError: Java heap space
或OutOfMemoryError: gc overhead limit exceeded
中看到错误。
解决方法 resolution
原因
此类问题可能有很多原因。
一个可能的原因是Java应用程序,在我们的例子中,CRX / CQ是从命令行启动的,默认栈内存设置为Java。 这意味着 jvm 参数 -Xmx
未指定。 CRX 或 CQ 至少需要分配 256 MB 的堆才能运行。 如果这是问题所在,则从命令行开始,请确保设置了堆内存设置。 示例:
java -Xmx512m -jar *.jar
如果不是这种情况,那么您的应用程序可能会保留太多对象而没有为垃圾收集释放它们。这称为内存泄漏,请参阅此处了解更多信息。请参阅下面有关如何分析Java应用程序中的内存问题的部分。
创建栈转储:
自动生成栈转储
要在内存不足时自动创建栈转储,可以添加jvm参数-XX:+HeapDumpOnOutOfMemoryError
以在应用程序抛出OutOfMemoryError时自动生成栈转储。 例如,
java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar
只要java进程内存不足,就会在进程的工作目录中生成栈转储文件(java_...hprof
)。 生成堆转储后,该进程可以继续运行。通常,一个堆转储文件就足以分析问题。
注意: 如果您正在使用 crx-quickstart/server/start
脚本来启动 CRX 实例,则您可以添加 -XX:+HeapDumpOnOutOfMemoryError
到 CQ_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
文件夹):
-
查找您正在为其生成栈转储的java进程的pid。
- 在Unix或Linux中,此操作可以使用
ps -ef | grep java
或jps -l
完成 - 在Windows中,这可以通过打开任务管理器来完成,按
Ctrl+Shift+Esc
,然后转到 查看,然后转到 选择列,然后转到 PID (进程标识符) 或jps -l
- 在Unix或Linux中,此操作可以使用
-
运行下面的 jmap 命令,使用您要生成堆转储文件的位置替换
/path/to/generate/heapdumpfile.hprof
,然后使用您在上一步中查找的 pid 替换1234
。code language-none 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内存分析器)。
此工具无法分析 IBM JVM 生成的转储。 对于以上问题,有几种可能性。 IBM HeapAnalyzer将适用于PHD或传统格式的栈转储。
[br>要进行完整的系统转储分析,请使用IBM支持助理工作台,其顶部安装有适用于Java的IBM监控和诊断工具 — 内存分析器。 栈直方图是对每个Java类使用的活动对象和内存数量的简单测量。 遗憾地是,所需的工具取决于Java安装,可能不可用或可能并不总是有效。 要创建栈直方图,您首先需要Java进程的进程ID。 要获取它,请运行ps or (if available), run:
<b](br>要进行完整的系统转储分析,请使用IBM支持助理工作台,其顶部安装有适用于Java的IBM监控和诊断工具 — 内存分析器。 栈直方图是对每个Java类使用的活动对象和内存数量的简单测量。 遗憾地是,所需的工具取决于Java安装,可能不可用或可能并不总是有效。 要创建栈直方图,您首先需要Java进程的进程ID。 要获取它,请运行ps or (if available), run:
<b)栈直方图
栈直方图是对每个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 供应商和版本。
引用
[
1]
HotSpot VM的Oracle帮助中心>
故障排除指南[
2]
Oracle.com >
javas >
DebuggingOptions