Java 自带性能监控工具:监视和管理控制台 jconsole 的使用(转)

最近遇到了内存溢出问题,详细了解了下。

本文转自:http://blog.csdn.net/defonds/article/details/45064297

1. 前言

  • 想验证你对 jvm 配的一些调优参数(比如 Xms、Xmx 等)有没有起作用吗?
  • 想不想实时监控你自定义的线程池的在实际运行时的线程个数、有没有死锁?
  • 应用出现 java.lang.OutOfMemoryError: Java heap space,你知道需要去调整 Xms、Xmx。想不想实时监控你的 Java 应用的堆内存使用情况,并根据峰值等数据设置最适合你的 Xms、Xmx 等参数?
  • 应用出现 java.lang.OutOfMemoryError: PermGen space,你知道需要去调整 XX:PermSize、XX:MaxPermSize。想不想找到你的应用的永久区 PermGen 的使用峰值,并根据其去设置合理的 XX:PermSize、XX:MaxPermSize 等参数?
  • 我们都知道,JVM 堆内存划分为年轻代和年老代。JVM 默认下的年老代与年轻代的比例(即 XX:NewRatio,这个名字容易让人产生混淆,即认为是年轻代比年老代)为 2(即把 JVM 堆内存平均分成了三份,年老大占用了两份,而年轻代占用一份。参考资料 Sun Java System Application Server Enterprise Edition 8.2 Performance Tuning Guide),这个比例并不适合所有情况,特别是当你的应用里局部变量远远大于全局变量,而且大量局部变量生命周期都很短的时候。如何根据应用实时的运行运行情况合理配置年轻代(Young Generation,即 Eden 区和两个 Survivor 区之和)和年老代(Old Generation,即 Tenured 区)的比例 XX:NewRatio 值?

Java 自带性能监控工具:监视和管理控制台 jconsole,它可以提供 Java 某个进程的内存、线程、类加载、jvm 概要以及 MBean 等的实时信息,也许能够对以上问题提供参考。


2. JVM 一些参数

在启动 jconsole 之前我们先来回顾一下 JVM 的一些主要参数:
  • -Xms 初始/最小堆内存大小
  • -Xmx 最大堆内存大小
  • -Xmn 年轻代大小
  • -XX:NewSize 年轻代大小
  • -XX:MaxNewSize 年轻代最大值
  • -XX:NewRatio 年老代与年轻代比值
  • -XX:MaxPermSize 持久代最大值
  • -XX:PermSize 持久代初始值
有些资料说,Xms、Xmx 设置的是 JVM 内存大小,是不对的,JVM 除了留给开发人员使用的堆内存之外还有非堆内存。

读者可能发现,有三种方式可以划分年轻代大小:-Xmn 方式、-XX:NewSize + -XX:MaxNewSize 方式、-XX:NewRatio 方式。三种都可以,优先级从高到低依次是 -XX:NewSize + -XX:MaxNewSize 方式、-Xmn 方式、-XX:NewRatio 方式,也就是说配置了前面优先级高的后面的优先级低的就被覆盖掉了。

这里插入一个怎么配置Java虚拟机的内存分配情况的配置说明:

本文向大家简单介绍一下进行JVM内存设置几种方法,安装Java开发软件时,默认安装包含两个文件夹,一个JDK(Java开发工具箱),一个JRE(Java运行环境,内含JVM),其中JDK内另含一个JRE。如果只是运行Java程序,则JRE已足够;而JDK则只有开发人员才用到。这里将为大家介绍设置JVM内存分配的几招。
  1.     -Xmx    Java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理内存大小及计算机内其他内存开销而定; 

        -Xms    Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值; 

        -Xmn    Java Heap Young区大小,不熟悉最好保留默认值;     -Xss    每个线程的Stack大小,不熟悉最好保留默认值;    

  2. 2. 如何分配JVM内存设置: 

        (1)当在命令提示符下启动并使用JVM时(只对当前运行的类Test生效):     java -Xmx128m -Xms64m -Xmn32m -Xss16m Test     (2)当在集成开发环境下(如eclipse)启动并使用JVM时: 

        a. 在eclipse根目录下打开eclipse.ini,默认内容为(这里设置的是运行当前开发工具的JVM内存分配):     -vmargs     -Xms40m     -Xmx256m

    -vmargs表示以下为虚拟机设置参数,可修改其中的参数值,也可添加-Xmn,-Xss,另外,eclipse.ini内还可以设置非堆内存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m. 

        此处设置的参数值可以通过以下配置在开发工具的状态栏显示:     在eclipse根目录下创建文件options,文件内容为:org.eclipse.ui/perf/showHeapStatus=true 

        修改eclipse根目录下的eclipse.ini文件,在开头处添加如下内容:     -debug  options     -vm  javaw.exe 

        重新启动eclipse,就可以看到下方状态条多了JVM信息. 

        b. 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效) 

        编辑当前使用的JRE,在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m 

        c. 打开eclipse-运行-运行-Java应用程序(只对所设置的java类生效)     选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m 

    选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m 

        注:如果在同一开发环境中同时进行了b和c设置,则b设置生效,c设置无效,如: 

        开发环境的设置为:-Xmx256m,而类Test的设置为:-Xmx128m -Xms64m,则运行Test时生效的设置为:     -Xmx256m -Xms64m 

        (3)当在服务器环境下(如Tomcat)启动并使用JVM时(对当前服务器环境下所以Java程序生效):     a. 设置环境变量:     变量名:CATALINA_OPTS 

        变量值:-Xmx128m -Xms64m -Xmn32m -Xss16m

  3. 3

     b. 打开Tomcat根目录下的bin文件夹,编辑catalina.bat,将其中

    的%CATALINA_OPTS%(共有四处)替换为:-Xmx128m -Xms64m -Xmn32m -Xss16m 



3. 本机启用 jconsole 以监控 Java 进程

CMD 切换到 %JAVA_HOME%/bin 目录,直接执行 jconsole
CMD 切换到 JAVA_HOME bin 目录,直接执行 jconsole

即可打开 Java 监视和管理控制台:
即可打开 Java 监视和管理控制台

本地进程列表里显示了所有本地执行中的 Java 进程,双击你感兴趣的那个进程(比如 PID 为 8504 那个),即可对该进程进行监控了:
双击你感兴趣的那个进程


4. 远程监控 Java 进程

要对 Java 进程进行远程监控,在启动它的时候需要启用 JMX。
以远程主机上的 tomcat 为例,先为 jmx 找一个可用的远程端口,比如 9999:
先为 jmx 找一个可用的远程端口

No news is good news~在 %TOMCAT_HOME%/bin/catalina.sh 文件的前面加上以下配置:
[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. JAVA_OPTS="-Xms1024m -Xmx2048m -XX:MaxPermSize=128m -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"  


如图
tomcat的JAVA_OPTS配置

【博主 20150526 加注:开始】这样写在 tomcat 关闭的时候(执行 %tomcat%/bin/shutdown.sh)会报端口已使用异常:

错误: 代理抛出异常错误: java.rmi.server.ExportException: Port already in use: 9999; nested exception is: 
        java.net.BindException: 地址已在使用

这是因为 tomcat 在启动、停止的时候都会执行 JAVA_OPTS 配置。这样就只能使用 kill -9 来关闭 tomcat 了...

解决办法是把监控配置写在 CATALINA_OPTS 里:

JAVA_OPTS="-Xms1024m -Xmx2048m -XX:MaxPermSize=128m"
CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

就可以了。CATALINA_OPTS 配置只是在 tomcat 启动的时候执行。参考资料:https://bowerstudios.com/node/636。【博主 20150526 加注:结束】

然后重启 tomcat,在本机打开 Java 监视和管理控制台,"远程进程" 输入远程主机名和 jmx 端口号:

jmx 远程连接

点击 "连接" 按钮,即可对远程主机上的 tomcat 进行实时监控了:
即可对远程主机上的 tomcat 进行实时监控了


5. jconsole 提供的一些有用信息

接着第 4 步的案例往下看。

5.1. JVM 设定信息是否起作用检查

点击 "VM 概要" 可以查看到刚才我们设定的 JAVA_OPTS 的一些参数已经奏效了:
JAVA_OPTS 的一些参数已经奏效

5.2. tomcat 线程池、自定义线程池数量情况实时监控

还在为 tomcat 线程池的神秘面纱而头疼?还在为自己定义的线程池 "黑盒" 一般而苦恼?看看下图:
tomcat线程情况

我们的 tomcat 刚启动,从上图可以看出只有一个 http-8080-Acceptor-0 线程,我们去访问一下我们的项目,然后再回来看看:
http-8080 线程一下子增长到了 8 个

http-8080 线程一下子增长到了 8 个。是不是一切一目了然,尽在掌握之中?

5.3. 内存使用实际消耗

点击 Java 监视和管理控制台 "内存" 叶项,可以看到 tomcat 堆内存的使用情况:
tomcat 堆内存的使用情况

图表里有很多选项:
图表里有很多选项

我们看一下 Eden 区:
Eden区

Eden 区基本和整个堆内存的走势差不多。再看 Survivor 区:
Survivor区

Survivor 区在较短时间内的走势相对平稳。再看 Old Gen 区:
再看 Old Gen 区

这个走势更加平稳,而且对比 Survivor 区、Old Gen 区两张图,可以很明显地看出,在大约 19:58 那个时刻有将一批对象从 Survivor 区移到 Old Gen 区。最后看 Perm Gen 区。
这个走势最平稳了。可以明显看出,在大约 19:58,在我们访问一下我们的项目的时候,一些新的 class 等静态资源加载到了 JVM 中。5.4 的加载类数的图也证实了这一点。

5.4. tomcat 加载类的情况

tomcat 加载类的情况


6. 配合 jmap 的使用

先找到我们 tomcat 进程的 PID 是 13863

先找到我们 tomcat 进程的 PID 是 13863,然后执行 jmap -heap 13863:
jmap -heap 13863

Heap Configuration 里列的基本就是我们刚才配的那些,比如 MaxHeapSize 是 2048 MB,MaxPermSize 是 128 MB。这个和 5.1 里的是一样的。


参考资料

相关推荐
<p> 需要学习Windows系统YOLOv4的同学请前往《Windows版YOLOv4目标检测实战:原理与源码解析》, </p> <p> 课程链接 https://edu.csdn.net/course/detail/29865 </p> <h3> <span style="color:#3598db;">【为什么要学习这门课】</span> </h3> <p> <span>Linux</span>创始人<span>Linus Torvalds</span>有一句名言:<span>Talk is cheap. Show me the code. </span><strong><span style="color:#ba372a;">冗谈不够,放码过来!</span></strong> </p> <p> <span> </span>代码阅读是从基础到提高的必由之路。尤其对深度学习,许多框架隐藏了神经网络底层的实现,只能在上层调包使用,对其内部原理很难认识清晰,不利于进一步优化和创新。 </p> <p> YOLOv4是最近推出的基于深度学习的端到端实时目标检测方法。 </p> <p> YOLOv4的实现darknet是使用C语言开发的轻型开源深度学习框架,依赖少,可移植性好,可以作为很好的代码阅读案例,让我们深入探究其实现原理。 </p> <h3> <span style="color:#3598db;">【课程内容与收获】</span> </h3> <p> 本课程将解析YOLOv4的实现原理和源码,具体内容包括: </p> <p> - YOLOv4目标检测原理<br /> - 神经网络及darknet的C语言实现,尤其是反向传播的梯度求解和误差计算<br /> - 代码阅读工具及方法<br /> - 深度学习计算的利器:BLAS和GEMM<br /> - GPU的CUDA编程方法及在darknet的应用<br /> - YOLOv4的程序流程 </p> <p> - YOLOv4各层及关键技术的源码解析 </p> <p> 本课程将提供注释后的darknet的源码程序文件。 </p> <h3> <strong><span style="color:#3598db;">【相关课程】</span></strong> </h3> <p> 除本课程《YOLOv4目标检测:原理与源码解析》外,本人推出了有关YOLOv4目标检测的系列课程,包括: </p> <p> 《YOLOv4目标检测实战:训练自己的数据集》 </p> <p> 《YOLOv4-tiny目标检测实战:训练自己的数据集》 </p> <p> 《YOLOv4目标检测实战:人脸口罩佩戴检测》<br /> 《YOLOv4目标检测实战:中国交通标志识别》 </p> <p> 建议先学习一门YOLOv4实战课程,对YOLOv4的使用方法了解以后再学习本课程。 </p> <h3> <span style="color:#3598db;">【YOLOv4网络模型架构图】</span> </h3> <p> 下图由白勇老师绘制 </p> <p> <img alt="" src="https://img-bss.csdnimg.cn/202006291526195469.jpg" /> </p> <p>   </p> <p> <img alt="" src="https://img-bss.csdnimg.cn/202007011518185782.jpg" /> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页