如何监控和诊断JVM堆内和堆外内存使用?
上一讲我介绍了JVM内存区域的划分,总结了相关的一些概念,今天我将结合JVM参数、工具等方面,进一步分析JVM内存结构,包括外部资料相对较少的堆外部分
今天我要问你的问题是,如何监控和诊断JVM堆内和堆外内存使用?
典型回答
-
了解JVM内存的方法有很多,具体能力范围也有区别,简单总结如下:
- 可以使用综合性的图形化工具,如JConsole、VisualVM(注意,从Oracle JDK 9开始,VisualVM已经不再包含在JDK安装包中)等。这些工具具体使用起来相对比较直观,直接连接到Java进程,然后就可以在图形化界面里掌握内存使用情况
-
以JConsole为例,其内存页面可以显示常见的堆内存和各种堆外部分使用状态
- 也可以使用命令行工具进行运行时查询,如jstat和jmap等工具都提供了一些选项,可以查看堆、方法区等使用数据
- 或者,也可以使用jmap等提供的命令,生成堆转储(Heap Dump)文件,然后利用jhat或Eclipse MAT等堆转储分析工具进行详细分析
- 如果你使用的是Tomcat、Weblogic等Java EE服务器,这些服务器同样提供了内存管理相关的功能
- 另外,从某种程度上来说,GC日志等输出,同样包含着丰富的信息
-
这里有一个相对特殊的部分,就是是堆外内存中的直接内存,前面的工具基本不适用,可以使用JDK自带的Native Memory Tracking(NMT)特性,它会从JVM本地内存分配的角度进行解读
考点分析
- 今天选取的问题是Java内存管理相关的基础实践,对于普通的内存问题,掌握上面我给出的典型工具和方法就足够了。这个问题也可以理解为考察两个基本方面能力,第一,你是否真的理解了JVM的内部结构;第二,具体到特定内存区域,应该使用什么工具或者特性去定位,可以用什么参数调整
- 对于JConsole等工具的使用细节,我在专栏里不再赘述,如果你还没有接触过,你可以参考JConsole官方教程。我这里特别推荐Java Mission Control(JMC),这是一个非常强 大的工具,不仅仅能够使用JMX进行普通的管理、监控任务,还可以配合Java Flight Recorder(JFR)技术,以非常低的开销,收集和分析JVM底层的Profling和事件等信息。目 前, Oracle已经将其开源,如果你有兴趣请可以查看OpenJDK的Mission Control项目
- 关于内存监控与诊断,我会在知识扩展部分结合JVM参数和特性,尽量从庞杂的概念和JVM参数选项中,梳理出相对清晰的框架:
- 细化对各部分内存区域的理解,堆内结构是怎样的?如何通过参数调整?
- 堆外内存到底包括哪些部分?具体大小受哪些因素影响?