以编程方式打印类直方图

时间:2010-09-21 12:51:34

标签: java class instance histogram

有没有办法以编程方式在当前的java应用程序上打印最常用的N类?

样本输出:N = 10

num   #instances    #bytes  class name
--------------------------------------
  1:        23     4723136  [I
  2:        19     4718928  [J
  3:        18     4718880  [D
  4:     73925     1774200  java.lang.String
  5:       208     1226400  [C
  6:        28     1205064  [B
  7:        18     1179936  [F
  8:        68      297040  [Ljava.lang.String;
  9:       332       14136  [Ljava.lang.Object;
 10:        32       10240  <objArrayKlassKlass>

5 个答案:

答案 0 :(得分:3)

您可以将jmap作为java包装器脚本的一部分启动并在循环中连续运行:

例如,如果您使用的是Unix,则可以执行以下操作:

java MyMainClass ... &

pid=$!
while [ ! -z $pid ]
do
    jmap -histo $pid | head -13
    sleep 60

    #check pid
    kill -0 $pid > /dev/null 2>&1   
    if [ $? -ne 0 ]
    then
       pid=""
    fi  
done

答案 1 :(得分:0)

可能不是没有通过JVM Tool Interface (JVM TI)或篡改Object的实现(这是一项棘手的业务)。

这篇文章可能很有用:Creating a Debugging and Profiling Agent with JVMTI

答案 2 :(得分:0)

如果您指的是最常用的顶级类,您可以在构造函数周围定义切入点并跟踪每种类型的初始化。你可以使用AspectJ。

答案 3 :(得分:0)

我认为你不能在同一个JVM中做到这一点,因为你需要遍历对象堆,并且最终可能会进入无限循环。出于好奇,我尝试使用jmap针对同一个JVM生成Runtime.exec,甚至针对不同的JVM,它只是挂起?

String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
//pid=2520
System.out.println("PID: " + pid);
Process p = Runtime.getRuntime().exec("jmap -histo " + pid);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line ;
while((line = br.readLine())!=null){
    System.out.println(line);
}

br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while((line = br.readLine())!=null){
    System.out.println(line);
}

答案 4 :(得分:0)

您可以通过编程方式使用Runtime#exec来运行jmap,如下所示:

String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
Process p = Runtime.getRuntime().exec("jmap -histo " + pid);

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}
br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = br.readLine()) != null) {
    System.out.println("ERR:" + line);
}
p.waitFor();

输出将是:

 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:         55905       40469648  [B (java.base@11.0.2)
   2:          5292        7240256  [I (java.base@11.0.2)
   3:         24865         596760  java.lang.String (java.base@11.0.2)
   4:          5422         347008  java.net.URL (java.base@11.0.2)
   5:          5242         327088  [Ljava.lang.Object; (java.base@11.0.2)
...