jrockit_JRockit JRCMD教程

jrockit

本文将为您提供概述和教程,说明如何使用jrcmd工具对JRockit Java Heap问题进行初始分析和问题隔离。 将来的文章中将介绍使用JRockit任务控制和堆转储分析(仅JRockit R28 +版)的更深入的分析和教程。

有关JRockit Java堆空间的快速概述,请查阅以下文章:
JRockit Java堆空间

JRCMD工具概述

jrcmd是一个免费工具,可以在JRockit二进制文件中直接使用。 它允许您从运行时JRockit VM生成和收集关键数据,例如:

  • Java进程内存空间细分(Java堆与本机内存空间)
  • Java堆诊断(直方图)– Java加载的类
  • 按需JRockit堆转储生成(仅版本R28 +)
  • 线程转储生成
  • 更多…

对于本文,我们创建了一个内部泄漏的简单Java程序。 我们将使用该程序来演示如何利用jrcmd进行初始分析。

示例Java内存泄漏程序

这个简单的Java程序只是将String数据添加到静态HashMap中,然后慢慢泄漏到JVM耗尽Java Heap内存的地步。 该程序将允许您通过JRockit jrcmd可视化一个缓慢增长的Java堆泄漏。 请注意,此示例使用了128 MB(-Xms128m –Xmx128m)的Java堆大小。

/**
 
 * JavaHeapLeakSimulator
 * @author Pierre-Hugues Charbonneau
 * http://javaeesupportpatterns.blogspot.com
 */
 
public class JavaHeapLeakSimulator {
 
        private final static int NB_ITERATIONS = 500000000;
        // ~1 KB data footprint
 
        private final static String LEAKING_DATA_PREFIX = "datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata
datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata
datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata
datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata
datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata
datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata";
 
        // Map used to stored our leaking String instances
        private static Map<String, String> leakingMap;

        static { 
               leakingMap = new HashMap<String, String>();
        }
 
       /**
 
         * @param args
 
         */
 
        public static void main(String[] args) {
 
               System.out.println("Java Heap Leak Simulator 1.0"); 
               System.out.println("Author: Pierre-Hugues Charbonneau");
               System.out.println("http://javaeesupportpatterns.blogspot.com/");
 
               try {
 
                       for (int i = 0; i < NB_ITERATIONS; i++) {

                              String data = LEAKING_DATA_PREFIX + i;
                               
                              // Add data to our leaking Map data structure...
                              leakingMap.put(data, data);                             

                              // Slowdown the Java program so we can monitor the leak before the OutOfMemoryError condition
                              Thread.sleep(1);
 
                       }

               } catch (Throwable any) {

                       if (any instanceof java.lang.OutOfMemoryError) {
                              System.out.println("OutOfMemoryError triggered! "
                                             + any.getMessage() + " [" + any + "]");
                       } else {
 
                              System.out.println("Unexpected Exception! " + any.getMessage() 
                                             + " [" + any + "]");
                       }
               }

               System.out.println("JavaHeapLeakSimulator done!"); 
        }
}

JRCMD –初始执行

可以从托管要监视的JVM的本地服务器执行JRCMD,也可以通过JRockit Mission Control远程执行。 该可执行文件位于您使用的JRockit JDK中:

<JRockit_JDK_HOME>/bin/jrcmd

默认的jrcmd执行将返回您可以监视的活动JRockit Java进程ID的列表:

C:\Apps\Weblogic1035\jrockit_160_24_D1.1.2-4\bin>jrcmd
5360 org.ph.javaee.tool.oom.JavaHeapLeakSimulator
5952
6852 jrockit.tools.jrcmd.JrCmd

JRCMD – Java堆监视

下一步是开始监视Java Heap内存使用情况和直方图。 Java堆直方图是Java类实例最大池的快照。 这使您可以查明泄漏的数据类型。 Ple

您可以在print_object_summary(快速摘要)或heap_diagnostics(完全分解)之间选择。

C:\Apps\Weblogic1035\jrockit_160_24_D1.1.2-4\bin>jrcmd 5360 heap_diagnostics
 
Invoked from diagnosticcommand
 
======== BEGIN OF HEAPDIAGNOSTIC =========================
 
Total memory in system: 8465022976 bytes
Available physical memory in system: 5279170560 bytes
-Xmx (maximal heap size) is 134217728 bytes
Heapsize: 134217728 bytes
Free heap-memory: 123592704 bytes
 


--------- Detailed Heap Statistics: ---------
 
90.9% 3948k     5468  +3948k [C 
 3.0% 128k     5490   +128k java/lang/String
 2.1% 92k     3941    +92k java/util/HashMap$Entry
 1.2% 50k      461    +50k java/lang/Class
 0.8% 35k       21    +35k [Ljava/util/HashMap$Entry;
 0.6% 24k        7    +24k [B
 0.3% 15k      305    +15k [Ljava/lang/Object;
 0.3% 14k      260    +14k java/net/URL
 0.2% 6k      213     +6k java/util/LinkedHashMap$Entry
 0.1% 4k      211     +4k java/io/ExpiringCache$Entry
 0.1% 2k        4     +2k [Ljrockit/vm/FCECache$FCE;
 0.0% 1k       50     +1k [Ljava/lang/String;
 0.0% 1k       10     +1k java/lang/Thread
 0.0% 1k       61     +1k java/util/Hashtable$Entry
 0.0% 1k        7     +1k [I
 0.0% 0k       19     +0k java/util/HashMap
 0.0% 0k       19     +0k java/lang/ref/WeakReference
 0.0% 0k        7     +0k [Ljava/util/Hashtable$Entry;
 0.0% 0k       19     +0k java/util/Locale
 0.0% 0k       11     +0k java/lang/ref/SoftReference
 0.0% 0k        1     +0k [S
…………………………………………………

–第一列对应于Class对象类型对Java Heap占用量的贡献,以%为单位
–第二列对应于以K为单位的Class对象类型的内存占用量
–第三列对应于特定类型的Class实例的# –第四列对应于特定类型的增量– / +内存占用量

从上面的快照中可以看到,最大的数据类型是[C(在我们的例子中为char)和java.lang.String。 为了查看泄漏的数据类型,您将需要生成几个快照。 频率将取决于泄漏率。 在我们的示例中,在下面找到5分钟后拍摄的另一个快照:

# After 5 minutes
 
--------- Detailed Heap Statistics: ---------
 
93.9% 26169k    28746 +12032k [C
 2.4% 674k    28768   +295k java/lang/String
 2.3% 637k    27219   +295k java/util/HashMap$Entry
 0.9% 259k       21   +128k [Ljava/util/HashMap$Entry;
 0.2% 50k      462     +0k java/lang/Class
 0.1% 24k        7     +0k [B
# After 5 more minutes
 
--------- Detailed Heap Statistics: ---------
 
94.5% 46978k    50534 +20809k [C 
 2.4% 1184k    50556   +510k java/lang/String
 2.3% 1148k    49007   +510k java/util/HashMap$Entry
 0.5% 259k       21     +0k [Ljava/util/HashMap$Entry;
 0.1% 50k      462     +0k java/lang/Class

第三和第四列显示不断增加。 如您所见,在我们的案例中,泄漏数据为[C,java.lang.String和java.util.HashMap $ Entry,它们都从〜4 MB增加到28 MB,50 MB,并且还在不断增长……

通过这种方法很容易查明泄漏的数据类型,但是泄漏数据类型的来源(根本原因)呢? 这是jrcmd不再有用的地方。 更深入的内存泄漏分析将要求您使用JRockit Mission Control或堆转储分析(仅JRockit R28 +)。

最后一点,在确定真正的Java Heap泄漏之前,请确保在两次捕获之间至少有一个Full GC之后拍摄了jrcmd快照(您感兴趣的是OldGen泄漏,例如在主要GC集合中幸存的Java对象)。

JRCMD线程转储生成

线程转储分析对于与卡死的线程相关的问题至关重要,但对解决某些类型的Java Heap问题也很有用。 例如,它可以通过暴露在短时间内在Java Heap上分配大量内存的罪魁祸首Thread来查明Java Heap突然增加的原因。 可以使用jrcmd print_threads选项生成线程转储。

**在删除Thread.sleep()并增加Java堆容量之后,从我们的示例Java程序捕获了线程转储**

C:\Apps\Weblogic1035\jrockit_160_24_D1.1.2-4\bin>jrcmd 5808 print_threads
 
5808:
 



===== FULL THREAD DUMP ===============
 
Mon Apr 09 09:08:08 2012
 
Oracle JRockit(R) R28.1.3-11-141760-1.6.0_24-20110301-1429-windows-ia32
"Main Thread" id=1 idx=0x4 tid=6076 prio=5 alive, native_blocked
    at jrockit/vm/Allocator.getNewTla(II)V(Native Method)
    at jrockit/vm/Allocator.allocObjectOrArray(Allocator.java:354)[optimized]
    at java/util/Arrays.copyOfRange(Arrays.java:3209)[inlined]
    at java/lang/String.<init>(String.java:215)[inlined]
    at java/lang/StringBuilder.toString(StringBuilder.java:430)[optimized]
    at org/ph/javaee/tool/oom/JavaHeapLeakSimulator.main(JavaHeapLeakSimulator.java:38)
    at jrockit/vm/RNI.c2java(IIIII)V(Native Method)
    -- end of trace
……………………………………….

我们可以看到示例Java程序正在从执行JavaHeapLeakSimulator程序的“主线程”创建许多java.lang.String对象。

结论

我希望本文能帮助您理解可以利用JRockit jrcmd工具进行快速Java堆分析。 期待您的意见和问题。

未来的文章将包括更深入的JRockit Java堆和堆转储分析教程。

参考: Java EE支持模式和Java教程博客上的JCG合作伙伴 Pierre-Hugues Charbonneau的JRockit jrcmd教程


翻译自: https://www.javacodegeeks.com/2012/04/jrockit-jrcmd-tutorial.html

jrockit

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值