Java生产环境下性能监控

JVM参数查询

查看JVM运行时参数

这里主要介绍如下几个工具:
1、jps:查看本机java进程信息。
2、jstack:打印线程的栈信息,制作线程dump文件。
3、jmap:打印内存映射,制作堆dump文件
4、jstat:性能监控工具
5、jhat:内存分析工具
6、jconsole:简易的可视化控制台
7、jvisualvm:功能强大的控制台
Java Dump:
Java Dump就是虚拟机运行时的快照,将虚拟机运行时的状态和信息保存到文件中:
线程dump:包含所有线程的运行状态,纯文本格式
堆dump:包含所有堆对象的状态,二进制格式
java dump可以在任何java环境使用,信息量充足,针对非功能性性的bug,主要为多线程开发、内存泄漏。

jstat查看JVM统计信息

主要是对java应用程序的资源和性能进行实时的命令行监控,包括了对heap size和垃圾回收状况的监控。
jstat

  • option:我们经常使用的选项有gc、gcutil
  • vmid:java进程id
  • interval:间隔时间,单位为毫秒
  • count:打印次数

1、jstat -gc PID 5000 20

《Java生产环境下性能监控》 jstat1.png

  • S0C:年轻代第一个survivor的容量(字节)
  • S1C:年轻代第二个survivor的容量(字节)
  • S0U:年轻代第一个survivor已使用的容量(字节)
  • S1U:年轻代第二个survivor已使用的容量(字节)
  • EC:年轻代中Eden的空间(字节)
  • EU:年代代中Eden已使用的空间(字节)
  • OC:老年代的容量(字节)
  • OU:老年代中已使用的空间(字节)
  • PC:永久代的容量
  • PU:永久代已使用的容量
  • YGC:从应用程序启动到采样时年轻代中GC的次数
  • YGCT:从应用程序启动到采样时年轻代中GC所使用的时间(单位:S)
  • FGC:从应用程序启动到采样时老年代中GC(FULL GC)的次数
  • FGCT:从应用程序启动到采样时老年代中GC所使用的时间(单位:S)

2、jstat -gcutil PID 5000 20

《Java生产环境下性能监控》 jstat2.png

  • s0:年轻代中第一个survivor已使用的占当前容量百分比
  • s1:年轻代中第二个survivor已使用的占当前容量百分比
  • E:年轻代中Eden已使用的占当前容量百分比
  • O:老年代中已使用的占当前容量百分比
  • P:永久代中已使用的占当前容量百分比

导出内存影响文件

内存溢出自动导出

-XX:+HeapDumpOnOutOfMemoryError  // 当内存溢出的时候自动导出映像文件
-XX:HeapDumpPath=./     // 导出映像文件的路径

上面的这两个JVM 参数就可以在发生内存溢出的时候,自动将 heap 导出到设定的路径,后续进行内存分析的时候就可以查看
使用jamp命令手动导出映像文件

jmap -dump:format=b,file=heap.hprof 43939  // file 后面的文件可以自定义命名,43939

MAT分析内存溢出

  1. JProfiler简介JProfiler 是一个商业授权的Java剖析工具,由EJ技术有限公司,针对的Java EE和Java SE应用程序开发的。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler的是一个独立的应用程序,但其提供Eclipse和IntelliJ等IDE的插件。它允许两个内存剖面评估内存使用情况和动态分配泄漏和CPU剖析,以评估线程冲突。JProfiler直觉式的GUI让你可以找到性能瓶颈、抓出内存漏失(memory leaks)、并解决执行绪的问题。它让你得以对heap walker作资源回收器的root analysis,可以轻易找出内存漏失;heap快照(snapshot)模式让未被参照(reference)的对象、稍微被参照的对象、或在终结(finalization)队列的对象都会被移除;整合精灵以便剖析浏览器的Java外挂功能。
  2. JMeter简介Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。
    Apache jmeter 可以用于对静态的和动态的资源(文件,Servlet,Perl脚本,java 对象,数据库和查询,FTP服务器等等)的性能进行测试。它可以用于对服务器、网络或对象模拟繁重的负载来测试它们的强度或分析不同压力类型下的整体性能。你可以使用它做性能的图形分析或在大并发负载测试你的服务器/脚本/对象。

jstack与线程的状态

  1. 先上一张线程状态转换图

    《Java生产环境下性能监控》 线程状态图.png

    做如下说明:代码中共有除RUNNING之外的6种状态,为了表示线程正在执行,特加了RUNNING这种状态。我们需要重点关注RUNNABLE、BLOCKED、WAITING和TIME_WAITING四种状态,jstack打印的线程堆栈中也会时时出现。
    1)BLOCKED:很好理解,就是线程在等待获取锁进入同步块或者同步方法中。两个死锁的线程即是Blocked。
    2)WAITING:比BLOCKED状态进步一些,指我已经获得锁了,但由于有些条件不满足,我自己等会,调用object.wait()方法。等条件满足了,别的线程调用notify再叫我。另外也可以调用Thread.join()方法,顾名思义就是调用别的线程的join方法,让别人join进来先执行,那我就只能等会了。但是由于wait()和notify()以及notifyAll()用于协调对共享资源的存取,所以必须在synchronized块中使用。所以即便wait状态的线程被notfiy唤醒了,也需要再次获得锁,所以唤醒后进入Blocked状态。
    3)TIMED_WAITING:类比WAITING,差异是不需要notify()或者notifyAlL()方法唤醒,时间到了我自己醒了。另外sleep比较好理解,就是让当前线程睡一会,与wait的区别是它不释放锁。
    4)RUNNABLE不用多说,在JAVA虚拟机中已经在运行,但是在等待操作系统资源,比如CPU时间片。

  2. 模拟一段死循环代码
public class NewTask2 implements Runnable{

    @Override
    public void run() {
        while(true)
        {
            System.out.println("the thread name is:" + Thread.currentThread().getName());
        }
    }

}

public class DemoApplication {

public static void main(String[] args) throws Exception {        
    Thread t = new Thread(new NewTask2());
    t.run();
}
  1. 运行main函数,查看任务管理器,找到PID,2284

    《Java生产环境下性能监控》 运行main函数.png

  2. 使用Process Explorer工具,找到2284进程并查看属性。找到CPU占用最高线程TID,8840

    《Java生产环境下性能监控》 使用Process Explorer工具.png

  3. 将8840换算为16进制,即为2288,记下这个16进制数字
  4. 在cmd下执行jstack -l PID命令,即jstack -l 2284。可以看到nid=0x2288线程堆栈信息,线程状态为RUNNABLE和执行循环输出的代码行信息。另外也可以看到WAITING状态的线程

《Java生产环境下性能监控》 image.png

《Java生产环境下性能监控》 image.png

    原文作者:快乐的工程师
    原文地址: https://www.jianshu.com/p/596e032d2e28#comments
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞