Meet JVM OOM - cont'd

· 447 words · 1 minute read

接上篇。

Groovy 🔗

内存泄漏的原因还是因为不当使用了GroovyShell,因为需要动态的加载并执行生成的 groovy 脚本。Groovy是一门动态语言,每个方法调用都是动态分发。为了优化该过程,Groovy 使用了 MetaClassRegistry 来记录每个 MetaClass. 默认情况下,GroovyShell 使用全局的 ClassLoader 来动态加载脚本,过程中生成的 Weak Reference 无法被 GC 掉。

解决的办法在于两点:

  • 每个 GroovyShell 使用一个 ClassLoader
  • 用完 GroovyShell 后清除 MetaClassRegistry
GroovySystem.getMetaClassRegistry().removeMetaClass(script.getClass())

工具 🔗

在常用的几台机器上安装了 openjdk,以及 visualvm,方便随时查看。不过 Java的分析工具真是贼多。

jmap 🔗

jmap -clstats 之前没有成功的原因是,它需要装debuginfo包:

debuginfo-install java-1.8.0-openjdk-devel

jconsole/jstat 🔗

jstat 可以打印出很多有用的 JVM 统计信息。

$ jstat -class 17966
Loaded  Bytes  Unloaded  Bytes     Time
113136 240382.4    69286 155529.1     249.35

$ jstat -gc 17966
...

$ jstat -gccause 17966
...

jconsole 提供了图形界面监控和管理 Java 程序。

jconsole <pid>

Memory Analyzer 🔗

MAT不仅仅作为Eclipse的插件而存在,它还有 stand-alone 的安装包。试用了一下内存泄漏检查,运行了一会儿后说完成了,不知道分析结果在哪里,有点莫名奇妙。后来无意中发现, 分析结果在内存转储文件所在文件夹内,一个压缩好的zip文件。

comments powered by Disqus