zoukankan      html  css  js  c++  java
  • JVM监测&工具

      前几篇篇文章介绍了介绍了JVM的参数设置并给出了一些生产环境的JVM参数配置参考方案。正如之前文章中提到的JVM参数的设置需要根据应用的特性来进行设置,每个参数的设置都需要对JVM进行长时间的监测,并不断进行调整才能找到最佳设置方案。本文将介绍如果通过工具及Java api来监测JVM的运行状态,并详细介绍各工具的使用方法。

           需要监测的数据:(内存使用情况 谁使用了内存 GC的状况)

    内存使用情况--heap&PermGen

    @ 表示通过jmap –heap pid 可以获取的值

    # 表示通过jstat –gcutil pid 可以获取的值

    参数的查看可以通过多种方法 本文中只随机列出一种。

    描述 最大值 当前值 报警值
    堆内存 @Heap Configuration::MaxHeapSize
    sum(eden+servivor+old)
    sum(eden+servivor+old) 自设
    非堆内存 sum(perm+native)  
    Eden @Eden Space::capacity @Eden Space::used
    Survivor0 @From Space::capacity @From Space::used
    Survivor1 @To Space::capacity @To Space::used
    New gen
    (注意区别于Xmn参数设置)
    @New Generation::capacity
    Eden + 1 Survivor Space
    @New Generation::used
    Old gen @concurrent mark-sweep generation::capacity
    (CMS是对old区的gc,所以此处即表示old gen)
    @concurrent mark-sweep generation::capacity(CMS)::used 自设
    Perm Gen @Perm Generation::capacity @Perm Generation::used 自设
    内存使用情况--config
    描述 配置值
    MaxTenuringThreshold jinfo -flag MaxTenuringThreshold pid
    MinHeapFreeRatio @Heap Configuration::MinHeapFreeRatio
    MaxHeapFreeRatio @Heap Configuration::MaxHeapFreeRatio
    new gen gc @using … in the new generation
    old gen gc new gen gc声明下方
    类总数统计 ??

    内存使用情况—C heap

    • top or ps aux

    谁使用了内存

    • Heap
      jmap –histo
      jmap –dump ,then mat
    • C heap
      google perftools

    GC的状况

    描述 收集次数 收集时间 应用暂停时间
    Full GC #FGC #FGCT 设置-XX:+PrintGCApplicationStoppedTime后在日志中查看
    Young GC #YGC #YGCT 同上

    -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC  -XX:+PrintGCApplicationStoppedTime  -Xloggc:logs/gc.log

     

    常用工具介绍:jinfo jmap jstack jstat

    jinfo 

    • 可以从一个给定的java进程或core文件或远程debug服务器上获取java配置信息。包括java系统属性及JVM参数(command line flags)。注意在jvm启动参数中没有配置的参数也可使用jinfo –flag xxx pid输出默认值(很有用,但貌似一些简写的参数查不出来)。
    • 可以修改运行时的java 进程的opts。
    • 只有solaris和linux的JDK版本里有。
    • 使用方式可使用jinfo –h 查询。

    jmap

           观察运行中的jvm物理内存的占用情况。

           如果连用SHELL jmap -histo pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。

           参数很简单,直接查看jmap -h

           举例:

    jmap -heap pid

    jmap -dump:format=b,file=heap.hprof <pid>

     
    dump文件可以通过MemoryAnalyzer分析查看.网址:http://www.eclipse.org/mat/,可以查看dump时对象数量,内存占用,线程情况等。

    jstack

           观察jvm中当前所有线程的运行情况和线程当前状态

           如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有。

           参数很简单,直接查看jstack -h

           举例:

    jstack pid

    jstat

           JVM监测工具(Java Virtual Machine Statistics Monitoring Tool)。利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括各种堆和非堆的大小及其内存使用量、classloader、compiler、垃圾回收状况等。

    举例:

    jstat –printcompilation -h10 3024 250 600
         每250毫秒打印一次,一共打印600次 每隔10行显示一次head
    语法结构:
    Usage: jstat -help|-options
    jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

    参数介绍:

    • -h n 每隔几行输出标题
    • vmid VM的进程号,即当前运行的java进程号
    • -t 在第一列显示自JVM启动以来的时间戳
    • -J 修改java进程的参数。类似jinfo -flag <name>=<value>。例如-J-Xms48m 设置初始堆为48M。详见这里。这个参数挺有用的,可以在运行中调整参数以方便测试、监测。
    • -option option为要检测的参数。参数列表可通过jstat –options 获取。下面将分别介绍每个参数及输出字段的含义。
    class 统计class loader行为信息
    compiler 统计编译行为信息
    gc 统计jdk gc时heap信息
    gccapacity 统计堆内存不同代的heap容量信息
    gccause 统计gc的情况(同-gcutil)和引起gc的事件
    gcnew 统计gc时新生代的信息(相比gcutil更详细)
    gcnewcapacity 统计gc时新生代heap容量
    gcold 统计gc时,老年区的情况
    gcoldcapacity 统计gc时,老年区heap容量
    gcpermcapacity 统计gc时,permanent区heap容量
    gcutil 统计gc时,heap情况
    printcompilation 统计编译行为信息

    -class option:Class Loader Statistics

    Column Description
    Loaded Number of classes loaded.
    Bytes Number of Kbytes loaded.
    Unloaded Number of classes unloaded.
    Bytes Number of Kbytes unloaded.
    Time Time spent performing class load and unload operations.

    -compiler:HotSpot Just-In-Time Compiler Statistics

    Column Description
    Compiled Number of compilation tasks performed.
    Failed Number of compilation tasks that failed.
    Invalid Number of compilation tasks that were invalidated.
    Time Time spent performing compilation tasks.
    FailedType Compile type of the last failed compilation.
    FailedMethod Class name and method for the last failed compilation.

    -gc Option:Garbage-collected heap statistics

    Column Description
    S0C Current survivor space 0 capacity (KB).
    S1C Current survivor space 1 capacity (KB).
    S0U Survivor space 0 utilization (KB).
    S1U Survivor space 1 utilization (KB).
    EC Current eden space capacity (KB).
    EU Eden space utilization (KB).
    OC Current old space capacity (KB).
    OU Old space utilization (KB).
    PC Current permanent space capacity (KB).
    PU Permanent space utilization (KB).
    YGC Number of young generation GC Events.
    YGCT Young generation garbage collection time.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    -gccapacity Option:Memory Pool Generation and Space Capacities

    Column Description
    NGCMN Minimum new generation capacity (KB).
    NGCMX Maximum new generation capacity (KB).
    NGC Current new generation capacity (KB).
    S0C Current survivor space 0 capacity (KB).
    S1C Current survivor space 1 capacity (KB).
    EC Current eden space capacity (KB).
    OGCMN Minimum old generation capacity (KB).
    OGCMX Maximum old generation capacity (KB).
    OGC Current old generation capacity (KB).
    OC Current old space capacity (KB).
    PGCMN Minimum permanent generation capacity (KB).
    PGCMX Maximum Permanent generation capacity (KB).
    PGC Current Permanent generation capacity (KB).
    PC Current Permanent space capacity (KB).
    YGC Number of Young generation GC Events.
    FGC Number of Full GC Events.

    -gccause Option:Garbage Collection Statistics, Including GC Events

    Column Description
    LGCC Cause of last Garbage Collection.
    GCC Cause of current Garbage Collection.

           前面的字段与gcutil相同.

    -gcnew Option:New Generation Statistics

    Column Description
    S0C Current survivor space 0 capacity (KB).
    S1C Current survivor space 1 capacity (KB).
    S0U Survivor space 0 utilization (KB).
    S1U Survivor space 1 utilization (KB).
    TT Tenuring threshold.
    MTT Maximum tenuring threshold.
    DSS Desired survivor size (KB).
    EC Current eden space capacity (KB).
    EU Eden space utilization (KB).
    YGC Number of young generation GC events.
    YGCT Young generation garbage collection time.

    -gcnewcapacity Option:New Generation Space Size Statistics

    Column Description
    NGCMN           
    Minimum new generation capacity (KB). 
    NGCMX     Maximum new generation capacity (KB).
    NGC     Current new generation capacity (KB).
    S0CMX Maximum survivor space 0 capacity (KB).
    S0C Current survivor space 0 capacity (KB).
    S1CMX Maximum survivor space 1 capacity (KB).
    S1C Current survivor space 1 capacity (KB).
    ECMX Maximum eden space capacity (KB).
    EC Current eden space capacity (KB).
    YGC Number of young generation GC events.
    FGC Number of Full GC Events.

    -gcold Option:Old and Permanent Generation Statistics

    Column Description
    PC Current permanent space capacity (KB).
    PU Permanent space utilization (KB).
    OC Current old space capacity (KB).
    OU old space utilization (KB).
    YGC Number of young generation GC events.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    -gcoldcapacity Option:Old Generation Statistics

    Column Description
    OGCMN Minimum old generation capacity (KB).
    OGCMX Maximum old generation capacity (KB).
    OGC Current old generation capacity (KB).
    OC Current old space capacity (KB).
    YGC Number of young generation GC events.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    -gcpermcapacity Option: Permanent Generation Statistics

    Column Description
    PGCMN Minimum permanent generation capacity (KB).
    PGCMX Maximum permanent generation capacity (KB).
    PGC Current permanent generation capacity (KB).
    PC Current permanent space capacity (KB).
    YGC Number of young generation GC events.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    -gcutil Option:Summary of Garbage Collection Statistics

    Column Description
    S0 Survivor space 0 utilization as a percentage of the space's current capacity.
    S1 Survivor space 1 utilization as a percentage of the space's current capacity.
    E Eden space utilization as a percentage of the space's current capacity.
    O Old space utilization as a percentage of the space's current capacity.
    P Permanent space utilization as a percentage of the space's current capacity.
    YGC Number of young generation GC events.
    YGCT Young generation garbage collection time.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    -printcompilation Option: HotSpot Compiler Method Statistics

    Column Description
    Compiled Number of compilation tasks performed.
    Size Number of bytes of bytecode for the method.
    Type Compilation type.
    Method Class name and method name identifying the compiled method. Class name uses "/" instead of "." as namespace separator. Method name is the method within the given class. The format for these two fields is consistent with the HotSpot - XX:+PrintComplation option.

     

    Java api方式监测

           jre中提供了一些查看运行中的jvm内部信息的api,这些api包含在java.lang.management包中,此包中的接口是在jdk 5中引入的,所以只有在jdk 5及其以上版本中才能通过这种方式访问这些信息。下面简单介绍一下这包括哪些信息,以及如何访问。

           可以通过此api访问到运行中的jvm的类加载的信息、jit编译器的信息、内存分配的情况、线程的相关信息以及运行jvm的操作系统的信息。java.lang.management包中提供了9个接口来访问这些信息,使用ManagementFactory的静态get方法可以获得相应接口的实例,可以通过这些实例来获取你需要的相关信息。

           更详细的关于MBean的介绍参见Java SE 6 新特性: JMX 与系统管理

           demo1:查看一下当前运行的jvm中加载了多少个类。想详细了解如何使用这些api,可以参考java.lang.management包中的详细api文档。

    public class ClassLoaderChecker {
    public static void main( String[] args ) throws Exception {
          ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
          System.out.println( bean.getLoadedClassCount() );
        }
    }
    demo2:自定义Mbean Type,记录的数据可通过jconsole等工具或自写代码查看,

    //工具方法

    public static ObjectName register(String name, Object mbean) {
    try {
    ObjectName objectName = new ObjectName(name);

    MBeanServer mbeanServer = ManagementFactory
    .getPlatformMBeanServer();

    try {
    mbeanServer.registerMBean(mbean, objectName);
    } catch (InstanceAlreadyExistsException ex) {
    mbeanServer.unregisterMBean(objectName);
    mbeanServer.registerMBean(mbean, objectName);
    }

    return objectName;

    } catch (JMException e) {
    throw new IllegalArgumentException(name, e);
    }
    }

    //步骤一:定义Mbean接口:
    //随便定义
    public interface DemoMBean {
          public AtomicLong getInvokeCount();
    }
    //步骤二:实现接口,并注册:
    public class DemoImpl implements DemoMBean{
          public final static String DEFAULT_OBJECT_NAME_PREFIX = "com.redcreen.demo:type=demo";
          register("com.redcreen.demo:type=demo",DemoImpl.instance);
    }
    //可以通过jconsole中查看数据了
     

    JVM监控工具介绍

    jstack — 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有

    jconsole – jconsole是基于Java Management Extensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。

    jinfo – jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。

    jmap – jmap 可以从core文件或进程中获得内存的具体匹配情况,包括Heap size, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。

    jdb – jdb 用来对core文件和正在运行的Java进程进行实时地调试,里面包含了丰富的命令帮助您进行调试,它的功能和Sun studio里面所带的dbx非常相似,但 jdb是专门用来针对Java应用程序的。

    jstat – jstat利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。

    jps – jps是用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等。

    jstatd
    启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
    实例:jstatd -J-Djava.security.policy=my.policy

    my.policy文件需要自己建立,内如如下:
    grant codebase “file:$JAVA_HOME/lib/tools.jar” {
    permission java.security.AllPermission;
    };
    这是安全策略文件,因为jdk对jvm做了jaas的安全检测,所以我们必须设置一些策略,使得jstatd被允许作网络操作

    上面的操作没有通过,出现:

    Could not create remote object
    access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
    java.security.AccessControlException: access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
    at java.security.AccessController.checkPermission(AccessController.java:546)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
    at java.lang.System.setProperty(System.java:727)
    at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)

    create in your usr/java/bin the jstatd.all.policy file, with the content must be

    1. grant codebase “file:${java.home}/../lib/tools.jar” {

    2. permission java.security.AllPermission;

    3. };

    jps
    列出所有的jvm实例
    实例:
    jps
    列出本机所有的jvm实例

    1
    jps 192.168.0.77

    列出远程服务器192.168.0.77机器所有的jvm实例,采用rmi协议,默认连接端口为1099
    (前提是远程服务器提供jstatd服务)

    输出内容如下:

    1
    jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps

    6286 Jps
    6174  Jstat

    jconsole
    一个图形化界面,可以观察到java进程的gc,class,内存等信息。虽然比较直观,但是个人还是比较倾向于使用jstat命令(在最后一部分会对jstat作详细的介绍)。

    jinfo(linux下特有)
    观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
    实例:jinfo 2083
    其中2083就是java进程id号,可以用jps得到这个id号。
    输出内容太多了,不在这里一一列举,大家可以自己尝试这个命令。

    jstack(linux下特有)
    可以观察到jvm中当前所有线程的运行情况和线程当前状态
    jstack 2083
    输出内容如下:

    jmap(linux下特有,也是很常用的一个命令)
    观察运行中的jvm物理内存的占用情况。
    参数如下:
    -heap
    :打印jvm heap的情况
    -histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
    -histo:live :同上,但是只答应存活对象的情况
    -permstat:打印permanent generation heap情况

    命令使用:

    1
    jmap -heap 2083

    可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
    输出内容:

    1
    jmap -histo 2083 | jmap -histo:live 2083

    可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
    输出内容:

    写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。

    jstat
    最后要重点介绍下这个命令。
    这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
    具体参数如下:
    -class:统计class loader行为信息
    -compile:统计编译行为信息
    -gc:统计jdk gc时heap信息
    -gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
    -gccause:统计gc的情况,(同-gcutil)和引起gc的事件
    -gcnew:统计gc时,新生代的情况
    -gcnewcapacity:统计gc时,新生代heap容量
    -gcold:统计gc时,老年区的情况
    -gcoldcapacity:统计gc时,老年区heap容量
    -gcpermcapacity:统计gc时,permanent区heap容量
    -gcutil:统计gc时,heap情况
    -printcompilation:不知道干什么的,一直没用过。

    一般比较常用的几个参数是:
    jstat -class 2083 1000 10 (每隔1秒监控一次,一共做10次)
    输出内容含义如下:

    Loaded Number of classes loaded.
    Bytes Number of Kbytes loaded.
    Unloaded Number of classes unloaded.
    Bytes Number of Kbytes unloaded.
    Time Time spent performing class load and unload operations.

    jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
    输出内容含义如下:

    S0C Current survivor space 0 capacity (KB).
    EC Current eden space capacity (KB).
    EU Eden space utilization (KB).
    OC Current old space capacity (KB).
    OU Old space utilization (KB).
    PC Current permanent space capacity (KB).
    PU Permanent space utilization (KB).
    YGC Number of young generation GC Events.
    YGCT Young generation garbage collection time.
    FGC Number of full GC events.
    FGCT Full garbage collection time.
    GCT Total garbage collection time.

    输出内容:

    如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替jprofile等监控工具了,谁让它收费呢。呵呵。
    用命令的好处就是速度快,并且辅助于其他命令,比如grep gawk sed等,可以组装多种符合自己需求的工具。

    u              jps的用法

    用来查看JVM里面所有进程的具体状态包括进程ID,进程启动的路径等等。unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。

     

    1
    [root@localhost ~]# jps

    25517 Jps

    25444 Bootstrap

     

    u              jstack的用法

    如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stacknative stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stacknative stack的信息如果现在运行的java程序呈现hung的状态,jstack是非常有用的。目前只有在SolarisLinuxJDK版本里面才有。

     

    1
    [root@localhost bin]# jstack 25444

    Attaching to process ID 25917, please wait…

    Debugger attached successfully.

    Client compiler detected.

    JVM version is 1.5.0_08-b03

    Thread 25964: (state = BLOCKED)

    Error occurred during stack walking:

    sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:134)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:437)

            at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:48)

            at sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess.getCurrentFrameGuess(LinuxX86JavaThreadPDAccess.java:75)

            at sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:252)

            at sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:211)

            at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:50)

            at sun.jvm.hotspot.tools.JStack.run(JStack.java:41)

            at sun.jvm.hotspot.tools.Tool.start(Tool.java:204)

            at sun.jvm.hotspot.tools.JStack.main(JStack.java:58)

    Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.access$800(LinuxDebuggerLocal.java:34)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:431)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:109)

     

     

    Thread 25963: (state = IN_NATIVE)

    Error occurred during stack walking:

    sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:134)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:437)

            at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:48)

            at sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess.getCurrentFrameGuess(LinuxX86JavaThreadPDAccess.java:75)

            at sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:252)

            at sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:211)

            at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:50)

            at sun.jvm.hotspot.tools.JStack.run(JStack.java:41)

            at sun.jvm.hotspot.tools.Tool.start(Tool.java:204)

            at sun.jvm.hotspot.tools.JStack.main(JStack.java:58)

    Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.access$800(LinuxDebuggerLocal.java:34)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:431)

            at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:109)

    u              jstat的用法

    用以判断JVM是否存在内存问题呢?如何判断JVM垃圾回收是否正常?一般的top指令基本上满足不了这样的需求,因为它主要监控的是总体的系统资源,很难定位到java应用程序。

    JstatJDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于javabin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。由于JVM内存设置较大,图中百分比变化不太明显

    一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。

    jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。

     

     

    语法结构:

    Usage: jstat -help|-options

           jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

     

    参数解释:

    Options — 选项,我们一般使用 -gcutil 查看gc情况

    vmid    — VM的进程号,即当前运行的java进程号

    interval– 间隔时间,单位为秒或者毫秒

    count   — 打印次数,如果缺省则打印无数次

     

    S0  — Heap上的 Survivor space 0 区已使用空间的百分比
    S1  — Heap
    上的 Survivor space 1 区已使用空间的百分比
    E   — Heap
    上的 Eden space 区已使用空间的百分比
    O   — Heap
    上的 Old space 区已使用空间的百分比
    P   — Perm space 
    区已使用空间的百分比
    YGC — 
    从应用程序启动到采样时发生 Young GC 的次数
    YGCT– 
    从应用程序启动到采样时 Young GC 所用的时间(单位秒)
    FGC — 
    从应用程序启动到采样时发生 Full GC 的次数

    FGCT– 
    从应用程序启动到采样时 Full GC 所用的时间(单位秒)
    GCT — 
    从应用程序启动到采样时用于垃圾回收的总时间(单位秒)

     

    实例使用1

    1
    [root@localhost bin]# jstat -gcutil 25444

      S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

     11.63   0.00   56.46  66.92  98.49 162    0.248    6      0.331    0.579

     

    实例使用2

    1
    [root@localhost bin]# jstat -gcutil 25444 1000 5

      S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

     73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

     73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

     73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

     73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

     73.54   0.00  99.04  67.52  98.49    166    0.252     6    0.331    0.583

     

    我们可以看到,5young gc之后,垃圾内存被从Eden space(E)放入了Old space(O),并引起了百分比的变化,导致Survivor space使用的百分比从73.54%(S0)降到0%(S1)。有效释放了内存空间。绿框中,我们可以看到,一次full gc之后,Old space(O)的内存被回收,从99.05%降到67.52%

    图中同时打印了young gcfull gc的总次数、总耗时。而,每次young gc消耗的时间,可以用相间隔的两行YGCT相减得到。每次full gc消耗的时间,可以用相隔的两行FGCT相减得到。例如红框中表示的第一行、第二行之间发生了1young gc,消耗的时间为0.252-0.2520.0秒。

    常驻内存区(P)的使用率,始终停留在98.49%左右,说明常驻内存没有突变,比较正常。

    如果young gcfull gc能够正常发生,而且都能有效回收内存,常驻内存区变化不明显,则说明java内存释放情况正常,垃圾回收及时,java内存泄露的几率就会大大降低。但也不能说明一定没有内存泄露。

    GCT YGCT FGCT的时间总和。

    以上,介绍了Jstat按百分比查看gc情况的功能。其实,它还有功能,例如加载类信息统计功能、内存池信息统计功能等,那些是以绝对值的形式打印出来的,比较少用,在此就不做介绍。

     

    1
    [root@localhost bin]# ps -ef | grep java

    root     25917     1  2 23:23 pts/2    00:00:05 /usr/local/jdk1.5/bin/java -Djava.endorsed.dirs=/usr/local/jakarta-tomcat-5.0.30/common/endorsed -classpath /usr/local/jdk1.5/lib/tools.jar:/usr/local/jakarta-tomcat-5.0.30/bin/bootstrap.jar:/usr/local/jakarta-tomcat-5.0.30/bin/commons-logging-api.jar -Dcatalina.base=/usr/local/jakarta-tomcat-5.0.30 -Dcatalina.home=/usr/local/jakarta-tomcat-5.0.30 -Djava.io.tmpdir=/usr/local/jakarta-tomcat-5.0.30/temp org.apache.catalina.startup.Bootstrap start

     

    jstat -class pid:显示加载class的数量,及所占空间等信息。

    实例使用3

    1
    [root@localhost bin]# jstat -class 25917

    Loaded  Bytes  Unloaded  Bytes     Time

    2629    2916.8       29   24.6     0.90

     

    jstat -compiler pid:显示VM实时编译的数量等信息。

    实例使用4

    1
    [root@localhost bin]# jstat -compiler 25917

    Compiled Failed Invalid   Time   FailedType FailedMethod

         768      0       0   0.70            0

     

    jstat –gccapacity :可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OCold内纯的占用量。

    1
    [root@localhost bin]# jstat -gccapacity 25917

    NGCMN       640.0

    NGCMX       4992.0

    NGC         832.0

    S0C         64.0

    S1C         64.0

    EC          704.0

    OGCMN       1408.0

    OGCMX       60544.0

    OGC         9504.0

    OC          9504.0                  OCold内纯的占用量

    PGCMN       8192.0                  PGCMN显示的是最小perm的内存使用量

    PGCMX       65536.0                 PGCMX显示的是perm的内存最大使用量

    PGC         12800.0                 PGC是当前新生成的perm内存占用量

    PC          12800.0                 PC是但前perm内存占用量

    YGC         164

    FGC         6

     

    jstat -gcnew pid: new对象的信息

    1
    [root@localhost bin]# jstat -gcnew 25917

     S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT

     64.0   64.0   47.4   0.0   2  15   32.0    704.0    145.7    168    0.254

     

    jstat -gcnewcapacity pid: new对象的信息及其占用量

    1
    [root@localhost bin]# jstat -gcnewcapacity 25917

     NGCMN  NGCMX   NGC   S0CMX  S0C   S1CMX  S1C   ECMX    EC      YGC   FGC

    640.0  4992.0  832.0 64.0   448.0 448.0  64.0   4096.0  704.0  168     6

     

    jstat -gcold pid: old对象的信息。

    1
    [root@localhost bin]# jstat -gcold 25917

       PC       PU        OC          OU       YGC    FGC    FGCT     GCT

     12800.0  12617.6     9504.0      6561.3   169     6    0.335    0.591

     

    jstat -gcoldcapacity pid:old对象的信息及其占用量。

    1
    [root@localhost bin]# jstat -gcoldcapacity 25917

    OGCMN      OGCMX        OGC         OC       YGC   FGC    FGCT     GCT

    1408.0     60544.0      9504.0      9504.0   169     6    0.335    0.591

     

    jstat -gcpermcapacity pid: perm对象的信息及其占用量。

    1
    [root@localhost bin]# jstat -gcpermcapacity 25917

    PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT

    8192.0    65536.0    12800.0    12800.0   169     6    0.335    0.591

     

    jstat -printcompilation pid:当前VM执行的信息。

    1
    [root@localhost bin]# jstat -printcompilation -h3  25917 1000 5

    1000毫秒打印一次,一共打印5次,还可以加上-h3每三行显示一下标题。

    Compiled  Size  Type Method

         788     73    1 java/io/File <init>

         788     73    1 java/io/File <init>

         788     73    1 java/io/File <init>

    Compiled  Size  Type Method

         788     73    1 java/io/File <init>

         788     73    1 java/io/File <init>

     

     

    u              jmap的用法

    打印出某个java进程(使用pid)内存内的,所有对象的情况(如:产生那些对象,及其数量)。

    可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。使用方法 jmap -histo pid。如果连用SHELL jmap -histo pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。jmap -dump:format=b,file=String 3024可以将3024进程的内存heap输出出来到String文件里。

     

    1
    [root@localhost bin]# jmap -histo  25917

    Attaching to process ID 26221, please wait…

    Debugger attached successfully.

    Client compiler detected.

    JVM version is 1.5.0_08-b03

    Iterating over heap. This may take a while…

    Unknown oop at 0xaa6e42d0

    Oop’s klass is null

     

    Object Histogram:

     

    Size    Count   Class description

    ——————————————————-

    3722768 30467   * ConstMethodKlass

    1976480 25334   char[]

    1907880 46994   * SymbolKlass

    1762088 2947    byte[]

    1709536 30467   * MethodKlass

    1487816 2600    * ConstantPoolKlass

    1009576 2600    * InstanceKlassKlass

    904880  2199    * ConstantPoolCacheKlass

    741432  30893   java.lang.String

    653576  4785    int[]

    351760  4397    java.lang.reflect.Method

    277824  2894    java.lang.Class

    248704  3401    short[]

    200888  4411    java.lang.Object[]

    193656  4045    java.lang.Object[]

    179744  5617    java.util.TreeMap$Entry

    175688  1800    java.util.HashMap$Entry[]

    165288  6887    java.util.HashMap$Entry

    104736  3273    java.lang.ref.SoftReference

    104136  4339    java.lang.ref.WeakReference

    96096   3521    java.lang.String[]

    86160   3590    java.util.Hashtable$Entry

    85584   3566    java.util.ArrayList

    83472   1206    java.util.Hashtable$Entry[]

    82944   1728    java.beans.MethodDescriptor

    80560   265     * ObjArrayKlassKlass

    69120   1728    java.util.HashMap

    52464   3055    java.lang.Class[]

    43040   1076    java.util.Hashtable

    42496   664     org.apache.commons.modeler.AttributeInfo

    37880   947     java.util.TreeMap

    33896   557     javax.management.modelmbean.ModelMBeanAttributeInfo[]

    33152   518     java.beans.PropertyDescriptor

    616     11      org.springframework.aop.framework.ProxyFactory

    608     19      java.util.PropertyPermission

    608     38      org.springframework.beans.MutablePropertyValues

    608     38      org.springframework.beans.factory.support.MethodOverrides

    608     2       * ArrayKlassKlass

    608     38      org.springframework.beans.factory.config.ConstructorArgumentValues

    608     4       org.apache.xerces.impl.XMLDTDScannerImpl

    576     24      java.util.Stack

    576     36      java.util.regex.Pattern$Category

    576     24      org.apache.naming.NamingEntry

    560     7       java.net.URL[]

    552     23      sun.management.MappedMXBeanType$BasicMXBeanType

    552     1       java.util.Locale[]

    552     22      java.io.ObjectStreamField[]

    544     17      java.util.Collections$SynchronizedMap

    176     11      java.util.regex.Pattern$Ctype

    8       1       sun.reflect.GeneratedMethodAccessor49

    8       1       sun.reflect.GeneratedMethodAccessor6

    8       1       sun.reflect.GeneratedConstructorAccessor10

    Heap traversal took 12.003 seconds.

     

    u              jinfo的用法

    可以输出并修改运行时的java 进程的opts。用处比较简单,就是能输出并修改运行时的java进程的运行参数。用法是jinfo -opt  pid 如:查看2788MaxPerm大小可以用  jinfo -flag MaxPermSize 2788

     

     

    u              jconsole的用法

    jconsole:一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM

    java写的GUI程序,用来监控VM,并可监控远程的VM,非常易用,而且功能非常强。命令行里打jconsole,选则进程就可以了

    不过我没有运行起来,老是报下面的错。会的朋友,帮忙看看。

    1
    [root@localhost bin]# jconsole

    Exception in thread “AWT-EventQueue-0″ java.awt.HeadlessException:

    No X11 DISPLAY variable was set, but this program performed an operation which requires it.        at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:159)

            at java.awt.Window.<init>(Window.java:317)

            at java.awt.Frame.<init>(Frame.java:419)

            at javax.swing.JFrame.<init>(JFrame.java:194)

            at sun.tools.jconsole.JConsole.<init>(JConsole.java:65)

            at sun.tools.jconsole.JConsole$4.run(JConsole.java:666)

            at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)

            at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)

            at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)

            at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)

            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)

            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)

            at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

    u              jdb的用法

    用来对core文件和正在运行的Java进程进行实时地调试,里面包含了丰富的命令帮助您进行调试,它的功能和Sun studio里面所带的dbx非常相似,但 jdb是专门用来针对Java应用程序的。


    JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有 jps、jstack、jmap、jhat、jstat、hprof等小巧的工具,本博客希望能起抛砖引玉之用,让大家能开始对JVM性能调优的常用工具 有所了解。

    现实企业级Java开发中,有时候我们会碰到下面这些问题:

    • OutOfMemoryError,内存不足

    • 内存泄露

    • 线程死锁

    • 锁争用(Lock Contention)

    • Java进程消耗CPU过高

    • ......

        这些问题在日常开发中可能被很多人忽视(比如有的人遇到上面的问题只是重启服务器或者调大内存,而不会深究问题根源),但能够理解并解决这些问题是 Java程序员进阶的必备要求。本文将对一些常用的JVM性能调优监控工具进行介绍,希望能起抛砖引玉之用。本文参考了网上很多资料,难以一一列举,在此 对这些资料的作者表示感谢!关于JVM性能调优相关的资料,请参考文末。

    A、 jps(Java Virtual Machine Process Status Tool)      

        jps主要用来输出JVM中运行的进程状态信息。语法格式如下:

        jps [options] [hostid]

        如果不指定hostid就默认为当前主机或服务器。

        命令行参数选项说明如下:

    -q 不输出类名、Jar名和传入main方法的参数
    -m 输出传入main方法的参数
    -l 输出main类或Jar的全限名
    - v   输出传入JVM的参数

        比如下面:

    root@ubuntu :/ # jps -m -l
    2458 org.artifactory.standalone.main.Main  /usr/local/artifactory-2 .2.5 /etc/jetty .xml
    29920 com.sun.tools.hat.Main -port 9998  /tmp/dump .dat
    3149 org.apache.catalina.startup.Bootstrap start
    30972 sun.tools.jps.Jps -m -l
    8247 org.apache.catalina.startup.Bootstrap start
    25687 com.sun.tools.hat.Main -port 9999 dump.dat
    21711 mrf-center.jar


    B、 jstack

        jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:

    jstack [option] pid
    jstack [option] executable core

    jstack [option] [server-id@]remote-hostname-or-ip


    命令行参数选项说明如下:

    l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
    -m mixed mode,不仅会输出Java堆栈信息,还会输出C /C ++堆栈信息(比如Native方法)

    jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。

    第一步先找出Java进程ID,我部署在服务器上的Java应用名称为mrf-center:

    root@ubuntu :/ # ps -ef | grep mrf-center | grep -v grep

    root     21711     1  1 14:47 pts/3    00:02:10 java -jar mrf-center.jar


    得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我这里用第三个,输出如下:

     JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

    TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程,用

    printf "%x " 21742

    得到21742的十六进制值为54ee,下面会用到。    

        OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下:


    root@ubuntu :/# jstack 21711 | grep 54ee

    "PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]

     可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),我找了下我的代码,定位到下面的代码:

    // Idle wait
    getLog().info( "Thread ["   + getName() +  "] is idle waiting..." );
    schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;
    long   now = System.currentTimeMillis();
    long   waitTime = now + getIdleWaitTime();
    long   timeUntilContinue = waitTime - now;
    synchronized (sigLock) {
         try   {
             if (!halted.get()) {
                 sigLock.wait(timeUntilContinue);
             }
         
         catch   (InterruptedException ignore) {
         }
    }

    它是轮询任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait()。


    C、 jmap(Memory Map)和jhat(Java Heap Analysis Tool)

        jmap用来查看堆内存使用状况,一般结合jhat使用。

        jmap语法格式如下:

    jmap [option] pid
    jmap [option] executable core

    jmap [option] [server-id@]remote-hostname-or-ip

    如果运行在64位JVM上,可能需要指定-J-d64命令选项参数。

    jmap -permstat pid

    打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息,如下图:

     JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

     使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。比如下面的例子:

    root@ubuntu:/ # jmap -heap 21711
    Attaching to process ID 21711, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 20.10-b01
     
    using thread- local   object allocation.
    Parallel GC with 4 thread(s)
     
    Heap Configuration:
        MinHeapFreeRatio = 40
        MaxHeapFreeRatio = 70
        MaxHeapSize      = 2067791872 (1972.0MB)
        NewSize          = 1310720 (1.25MB)
        MaxNewSize       = 17592186044415 MB
        OldSize          = 5439488 (5.1875MB)
        NewRatio         = 2
        SurvivorRatio    = 8
        PermSize         = 21757952 (20.75MB)
        MaxPermSize      = 85983232 (82.0MB)
     
    Heap Usage:
    PS Young Generation
    Eden Space:
        capacity = 6422528 (6.125MB)
        used     = 5445552 (5.1932830810546875MB)
        free       = 976976 (0.9317169189453125MB)
        84.78829520089286% used
    From Space:
        capacity = 131072 (0.125MB)
        used     = 98304 (0.09375MB)
        free       = 32768 (0.03125MB)
        75.0% used
    To Space:
        capacity = 131072 (0.125MB)
        used     = 0 (0.0MB)
        free       = 131072 (0.125MB)
        0.0% used
    PS Old Generation
        capacity = 35258368 (33.625MB)
        used     = 4119544 (3.9287033081054688MB)
        free       = 31138824 (29.69629669189453MB)
        11.683876009235595% used
    PS Perm Generation
        capacity = 52428800 (50.0MB)
        used     = 26075168 (24.867218017578125MB)
        free       = 26353632 (25.132781982421875MB)
        49.73443603515625% used
        ....


    使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象,如下:

    root@ubuntu:/ # jmap -histo:live 21711 | more
     
      num      #instances         #bytes  class name
    ----------------------------------------------
        1:         38445        5597736  <constMethodKlass>
        2:         38445        5237288  <methodKlass>
        3:          3500        3749504  <constantPoolKlass>
        4:         60858        3242600  <symbolKlass>
        5:          3500        2715264  <instanceKlassKlass>
        6:          2796        2131424  <constantPoolCacheKlass>
        7:          5543        1317400  [I
        8:         13714        1010768  [C
        9:          4752        1003344  [B
       10:          1225         639656  <methodDataKlass>
       11:         14194         454208  java.lang.String
       12:          3809         396136  java.lang.Class
       13:          4979         311952  [S
       14:          5598         287064  [[I
       15:          3028         266464  java.lang.reflect.Method
       16:           280         163520  <objArrayKlassKlass>
       17:          4355         139360  java.util.HashMap$Entry
       18:          1869         138568  [Ljava.util.HashMap$Entry;
       19:          2443          97720  java.util.LinkedHashMap$Entry
       20:          2072          82880  java.lang.ref.SoftReference
       21:          1807          71528  [Ljava.lang.Object;
       22:          2206          70592  java.lang.ref.WeakReference
       23:           934          52304  java.util.LinkedHashMap
       24:           871          48776  java.beans.MethodDescriptor
       25:          1442          46144  java.util.concurrent.ConcurrentHashMap$HashEntry
       26:           804          38592  java.util.HashMap
       27:           948          37920  java.util.concurrent.ConcurrentHashMap$Segment
       28:          1621          35696  [Ljava.lang.Class;
       29:          1313          34880  [Ljava.lang.String;
       30:          1396          33504  java.util.LinkedList$Entry
       31:           462          33264  java.lang.reflect.Field
       32:          1024          32768  java.util.Hashtable$Entry
       33:           948          31440  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;

    class name是对象类型,说明如下

    B  byte
    C  char
    D  double
    F  float
    I  int
    J  long
    Z  boolean
    [  数组,如[I表示int[]
    [L+类名 其他对象

    还有一个很常用的情况是:用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:

    jmap -dump:format=b,file=dumpFileName pid

    我一样地对上面进程ID为21711进行Dump:

    root@ubuntu:/ # jmap -dump:format=b,file=/tmp/dump.dat 21711     
    Dumping heap to  /tmp/dump .dat ...

    Heap dump file created


    dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:

    root@ubuntu:/ # jhat -port 9998 /tmp/dump.dat
    Reading from  /tmp/dump .dat...
    Dump  file   created Tue Jan 28 17:46:14 CST 2014
    Snapshot  read , resolving...
    Resolving 132207 objects...
    Chasing references, expect 26 dots..........................
    Eliminating duplicate references..........................
    Snapshot resolved.
    Started HTTP server on port 9998

    Server is ready.

    注意如果Dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在浏览器中输入主机地址:9998查看了:

     JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

    上面红线框出来的部分大家可以自己去摸索下,最后一项支持OQL(对象查询语言)。


    D、jstat(JVM统计监测工具)

        语法格式如下:

    jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]

    vmid是Java虚拟机ID,在Linux/Unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。比如下面输出的是GC信息,采样时间间隔为250ms,采样数为4:

    root@ubuntu:/ # jstat -gc 21711 250 4
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
    192.0  192.0   64.0   0.0    6144.0   1854.9   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649
    192.0  192.0   64.0   0.0    6144.0   1972.2   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649
    192.0  192.0   64.0   0.0    6144.0   1972.2   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649

    192.0  192.0   64.0   0.0    6144.0   2109.7   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649

    要明白上面各列的意义,先看JVM堆内存布局:

     可以看出:

    堆内存 = 年轻代 + 年老代 + 永久代
    年轻代 = Eden区 + 两个Survivor区(From和To)

    现在来解释各列含义:

    S0C、S1C、S0U、S1U:Survivor 0 /1 区容量(Capacity)和使用量(Used)
    EC、EU:Eden区容量和使用量
    OC、OU:年老代容量和使用量
    PC、PU:永久代容量和使用量
    YGC、YGT:年轻代GC次数和GC耗时
    FGC、FGCT:Full GC次数和Full GC耗时
    GCT:GC总耗时


    E、hprof(Heap/CPU Profiling Tool)

    hprof能够展现CPU使用率,统计堆内存使用情况。

        语法格式如下:

    java -agentlib:hprof[=options] ToBeProfiledClass
    java -Xrunprof[:options] ToBeProfiledClass

    javac -J-agentlib:hprof[=options] ToBeProfiledClass


    完整的命令选项如下:

    Option Name and Value  Description                    Default
    ---------------------  -----------                    -------
    heap=dump|sites|all    heap profiling                 all
    cpu=samples| times |old  CPU usage                      off
    monitor=y|n            monitor contention             n
    format =a|b             text(txt) or binary output     a
    file =< file >            write data to  file               java.hprof[.txt]
    net=<host>:<port>      send data over a socket        off
    depth=<size>           stack trace depth              4
    interval=<ms>          sample interval  in   ms          10
    cutoff=<value>         output cutoff point            0.0001
    lineno=y|n             line number  in   traces?         y
    thread=y|n             thread  in   traces?              n
    doe=y|n                dump on  exit ?                  y
    msa=y|n                Solaris micro state accounting n
    force=y|n              force output to < file >         y
    verbose=y|n            print messages about dumps     y


    来几个官方指南上的实例。

        CPU Usage Sampling Profiling(cpu=samples)的例子:

    java -agentlib:hprof=cpu=samples,interval=20,depth=3 Hello

    上面每隔20毫秒采样CPU消耗信息,堆栈深度为3,生成的profile文件名称是java.hprof.txt,在当前目录。 

        CPU Usage Times Profiling(cpu=times)的例子,它相对于CPU Usage Sampling Profile能够获得更加细粒度的CPU消耗信息,能够细到每个方法调用的开始和结束,它的实现使用了字节码注入技术(BCI):

    javac -J-agentlib:hprof=cpu=times Hello.java


    Heap Allocation Profiling(heap=sites)的例子:

    javac -J-agentlib:hprof=heap=sites Hello.java

    Heap Dump(heap=dump)的例子,它比上面的Heap Allocation Profiling能生成更详细的Heap Dump信息:

    javac -J-agentlib:hprof=heap=dump Hello.java

    虽然在JVM启动参数中加入-Xrunprof:heap=sites参数可以生成CPU/Heap Profile文件,但对JVM性能影响非常大,不建议在线上服务器环境使用。


    其他JVM性能调优参考资料:

    《Java虚拟机规范》

    《Java Performance》

    《Trouble Shooting Guide for JavaSE 6 with HotSpot VM》: http://www.oracle.com/technetwork/java/javase/tsg-vm-149989.pdf 

    《Effective Java》

    VisualVM: http://docs.oracle.com/javase/7/docs/technotes/guides/visualvm/

    jConsole: http://docs.oracle.com/javase/1.5.0/docs/guide/management/jconsole.html

    Monitoring and Managing JavaSE 6 Applications: http://www.oracle.com/technetwork/articles/javase/monitoring-141801.html

    BTrace:https://kenai.com/projects/btrace


    相关推荐文章:

    在 Java SE 6 中监视和诊断性能问题

     

    参考:

    http://www.51testing.com/?uid-183198-action-viewspace-itemid-185174

    JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat

    http://stl-www.htw-saarland.de/syst-lab/java/jdk-1_5_0/docs/tooldocs/share/jinfo.html

    http://qa.taobao.com/?p=10010

    运用Jconsole监控JVM

    http://www.coderanch.com/t/329407/java/java/find-all-loaded-classes-classloaders

    正因为当初对未来做了太多的憧憬,所以对现在的自己尤其失望。生命中曾经有过的所有灿烂,终究都需要用寂寞来偿还。
  • 相关阅读:
    电力三维基础信息平台
    基于三维GIS技术的输电线路地理信息系统的设计与实现
    linux学习笔记(1)
    linux学习笔记(4)
    linux学习笔记(8)
    linux学习笔记(6)
    linux学习笔记(3)
    linux 学习笔记(2)
    linux学习笔记(7)
    ASCII码表完整版
  • 原文地址:https://www.cnblogs.com/candlia/p/11920324.html
Copyright © 2011-2022 走看看