Permanent generation analysis with OQL

Java permanent generation holds holds data needed by the virtual machine to describe objects that do not have an equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation.

Let us see how OQL to analyze/understand Java permanent generation. Before proceeding, generate a sample heap dump. I created a sample heap dump from a Tomcat webserver instance on Solaris/sparc using jmap.

Let us ask few questions and try to answer those by OQL:

How many classes loaded in my app?

    select count(heap.classes())

We use the classes method of heap object and used count built-in to count the result of the same. The output was: 1950
How many of it bootstrap (i.e., Java platform classes loaded by JVM without using any java.lang.ClassLoader instance)?

    select count(heap.classes(), 'it.loader == null')

Note that we use a filter condition "it.loader == null". The output for this query was 1327. i.e., out of 1950 classes, 1327 are really bootstrap classes. Note that once loaded bootstrap classes are never unloaded (unlike other classes which could be unloaded if the classloader is dead. In other words, bootstrap loader is always alive)
Show each class loader and number of classes loaded by it
    
    select { loader: cl, count: cl.classes.elementCount }
    from instanceof java.lang.ClassLoader cl

Here we select multiple values for each loader (loader and count of classes) and so we use JavaScript object literal. instanceof keyword is used so that objects of all subclasses of java.lang.ClassLoader are selected. java.lang.ClassLoader has a private field of name 'classes' and of type java.util.Vector. This holds the classes loaded by it. We access the vector from each loader and print the count from it (elementCount as you'd expect is a private field of java.util.Vector class).
Show each loader and it's parent loader
ClassLoader instances form a parent-child chain. i.e, each loader can optionally hava a parent loader (or null). You may want to know parent loader of each loader:
 
    select { loader: cl, parent: cl.parent } 
    from instanceof java.lang.ClassLoader cl

As you'd have guessed, 'parent' is private field of java.lang.ClassLoader that points to the parent loader.
Show entire child-parent chain for each loader

    select map(heap.objects('java.lang.ClassLoader'), 
        function(it) {
            var res='';
            while (it != null) {
                res += toHtml(it) + "->";
                it = it.parent;
            }
            res += "null";
            return res + "<br>";
       })

Here we use map built-in to call a function (defined inline) on each class loader instance. The function returns a HTML string by walking all child-parent chain by a while-loop.
Show each loader and number of classes loaded by it -- but show it as a histogram (sort it by count of classes loaded)

    select map(sort(map(heap.objects('java.lang.ClassLoader'), 
   '{loader: it, count: it.classes.elementCount }'), 'lhs.count < rhs.count'),
   'toHtml(it) + "<br>"')

Explanation of the above query is left as exercise to reader :-)
Show each loader and classes loaded by it

    select { loader: cl,
             classes: filter(map(cl.classes.elementData, 'it'), 'it != null') }
    from instanceof java.lang.ClassLoader cl

As mentioned earlier, classes Vector has elementData array that holds the loaded classes. We filter null entries in it by filter built-in (note that a Vector can have more space allocated for possible future expansion. These slots will have nulls)
Show different types of ClassLoaders in the system. i.e., show different ClassLoader classes

    select unique(map(heap.objects('java.lang.ClassLoader'), 'classof(it)'))

Here we use unique built-in function to find unique classes of java.lang.ClassLoader instances.
How many classes were generated for reflection speed-up?
Hotspot JVM generates classes on-the-fly to speed up Java reflective calls (Constructor.newInstance, Method.invoke etc.). We want to find out how many such classes were generated. Piece of implementation detail before proceeding: All reflection speed-up classes are loaded by classloaders of type sun.reflect.DelegatingClassLoader. Each such loader only loads a single class.

    select count(heap.objects('sun.reflect.DelegatingClassLoader'))

Output for my Tomcat instance was 52. So, 52 classes were generated for reflection speedup.
Show liveness paths for each class loader
A Class are alive till the classloader that loaded it is alive. Let us say, you want to find out why your classloaders are live -- i.e, show all chain of references by which it is alive.

    select { loader: cl, liveness: heap.livepaths(cl) }
    from instanceof java.lang.ClassLoader cl

We have seen few OQL queries. One thing we missed: the output for these queries! The output from jhat will have hyperlinks. You can navigate Java objects,classes from query output objects easily. If you have still not downloaded Mustang, please do it now and play with jhat and do let us know your suggestions/comments!

Comments:

Post a Comment:
Comments are closed for this entry.
About

sundararajan

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks
Links

No bookmarks in folder

Blogroll

No bookmarks in folder

News

No bookmarks in folder