Eclipse MAT OQL 

Eclipse MAT is a prominent tool for analyzing heap dumps collected from a Java process. It has the usual features which we can expect while processing data that can be unearthed from a heap dump. We can see a Histogram which shows names of all classes loaded in the JVM along with their number of instances and cumulative heap size occupied by them. We can view list of all instances of a class, their static data members along with data members associated with each instance. We can dig deeper into any such data member. We can see all references incoming or outgoing in reference to an object. It is easy to see reference tree till "GC root" for one instance or merged over multiple/all instances of a class. We can see top dominators and suspects for memory leaks using this tool. We can list all threads used by the JVM, and inspect them for their stack traces and objects associated in context of code-lines there. It is possible to review all elements of any collection.

Arguably strongest feature offer by Eclipse MAT tool is a query interface where we can execute a query based on OQL (Object Query Language). 

References:

There are useful links from Eclipse sites on this tool:

1. Memory Analyzer

2. Memory Analyzer API

3. Eclipse MAT Wiki

OQL for counting instances of a class (and its subclasses) grouped by Class Name

Eclipse MAT Wiki page has a sample OQL for arranging instances of HashMap grouped by size:

SELECT s.sz AS Size, (SELECT OBJECTS m FROM java.util.HashMap m WHERE (m[0:-1].size() = s.sz)) AS Maps FROM OBJECTS ( SELECT DISTINCT h[0:-1].size() AS sz FROM java.util.HashMap h  ) s 

It takes quite a bit of time to execute and finally shows size of all the HashMap instances along with list of HashMap instances of that size.

A slightly more useful OQL is there which shows no. of instances of HashMap grouped on size is like this, as listed in the same Wiki page:

SELECT z.size AS Size, z.maps AS Maps, z.maps.@length AS Count, z.maps[0:-1].size() AS "Count (another way)" FROM OBJECTS ( eval((SELECT s.sz AS size, (SELECT OBJECTS m FROM java.util.HashMap m WHERE (m[0:-1].size() = s.sz)) AS maps FROM OBJECTS ( SELECT DISTINCT h[0:-1].size() AS sz FROM java.util.HashMap h  ) s )) ) z 

Following these examples, we can form OQLs for counting instances of some class in the JVM. For example, the following OQL counts number of instances of ClassLoader grouped by ClassName:

SELECT z.className AS ClassName, z.maps.@length AS Count FROM OBJECTS ( eval((SELECT s.sName AS className, (SELECT OBJECTS m FROM INSTANCEOF java.lang.ClassLoader m WHERE m.@clazz.@name.equals(s.sName)) AS maps FROM OBJECTS ( SELECT DISTINCT h.@clazz.@name AS sName FROM INSTANCEOF java.lang.ClassLoader h  ) s )) ) z 

To make another such OQL for a different class, we just need to replace java.lang.ClassLoader by full package path of that class.

For example, first inspect list of class names of the class:

SELECT h.@clazz.@name.toString() AS className FROM INSTANCEOF org.apache.logging.log4j.spi.AbstractLogger h 


Now formulate the group-by OQL by just replacing java.lang.ClassLoader by org.apache.logging.log4j.spi.AbstractLogger

SELECT z.className AS ClassName, z.maps.@length AS Count FROM OBJECTS ( eval((SELECT s.sName AS className, (SELECT OBJECTS m FROM INSTANCEOF org.apache.logging.log4j.spi.AbstractLogger m WHERE m.@clazz.@name.equals(s.sName)) AS maps FROM OBJECTS ( SELECT DISTINCT h.@clazz.@name AS sName FROM INSTANCEOF org.apache.logging.log4j.spi.AbstractLogger h  ) s )) ) z 

It produces the following output:





Comments

Popular posts from this blog