views:

68

answers:

4

is there any way to print top used N classes on the current java application programmaticly?

sample output: 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>
A: 

Probably not without going through JVM Tool Interface (JVM TI) or tampering with the implementation of Object (which is a tricky business).

This article is perhaps useful: Creating a Debugging and Profiling Agent with JVMTI.

aioobe
thank you for comments. I think using jmap source may be good option.. it is risky on live environment.. http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/tools/sun/tools/jmap/JMap.java.htm
Trustin
A: 

If you mean by top used, classes that are initialized most, you can define a pointcut around the constructors and keep track of the initializations for each type. You can use AspectJ for that matter.

hakan
I want do same thing with jmap -histo[:live] pid without changing our program. because system is live. i dont want to add overhead by adding such point cuts.also i cannot trust finilizer method for decrement the count.
Trustin
so you want to see the number of instances at a given point, i thought you wanted to see the total number of instances created. Then I think what you need is a profiling API. You can check java.lang.management package but I am not sure if it is possible to get instance counts
hakan
A: 

I don't think you can do it within the same JVM because you need to traverse the object heap, and you might end up going in an infinite loop. Just out of curiosity, I tried spawning jmap using Runtime.exec against the same JVM and even against a different JVM and it just hangs?

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);
}
dogbane
+2  A: 

You could kick off jmap as part of your java wrapper script and run it continuously in a loop:

For example, if you are on Unix, you could do something like:

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
dogbane