问题描述
我有一个使用Kubernetes编排在容器内运行的Java进程。我在docker stats中发现内存占用过多。
我有-Xmx=40Gb
,并且docker stats报告34.5 GiB
内存。为了更好地了解堆使用情况,我尝试使用以下命令对正在运行的进程进行堆转储:
jmap -dump:live,format=b,file=/tmp/dump.hprof $pid
但这会导致容器重新启动。生成的转储文件大约为9.5 GiB
,但是Eclipse Memory Analyzer报告该文件不完整,无法打开它。
Invalid HPROF file: Expected to read another 1,56,84,83,080 bytes,but only 52,82,104 bytes are available for heap dump record
在kubelet日志或容器日志中我没有找到太多信息,除了可能由堆转储引起的活动性探针故障?/
到目前为止,我无法重现该问题。我只是想了解可能发生的情况以及堆转储是否会干扰我的运行进程。我知道-dump:live
标志会强制执行GC周期,然后收集堆转储,这可能会干扰我的运行进程吗?
解决方法
当JVM承受压力时,我曾遇到过类似情况。您可以附加此文件hs_err_pid日志吗?检查完该文件后,可以将操作系统配置为生成核心转储(以防系统尚未生成核心文件),并且应该能够从核心文件中获取堆转储。
在下面的link中,您可以阅读与JDK错误相关的类似问题。
此外,我建议您使用这些标志启用垃圾收集器日志文件和自动堆转储。启用gc.log后,请附加它,并在存储中分配足够的空间以保存堆转储。
XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -Xloggc:/some/path/gc.log