I'm a software architect/consultant in Boulder, Colorado. I started blogging at: http://wayne-adams.blogspot.com/, but have since started the new blog, Data Sceintist in Training which will cover the areas I am learning as part of my own "big data" training, including the Hadoop family, frameworks like OpenStack, the R programming language, column-oriented databases and the art of examining data sets for useful patterns. The original blog will be kept alive with Java-specific posts. Wayne is a DZone MVB and is not an employee of DZone and has posted 35 posts at DZone. You can read more from them at their website. View Full User Profile

Java Profiling: Under the Covers

12.01.2009
| 29906 views |
  • submit to reddit

 

Intercepting bytecode

You probably noticed the unused Instrumentation parameter from our premain method above. When the Java runtime hands you an instance of an Instrumentation, you are provided the hook you need to provide your own ClassFileTransformer. ClassFileTransformer is an interface with a single method -- transform. It is in this transform method that you will get the opportunity to intercept the class bytecodes and instrument it or not, as you choose.

Next, we'll save the passed-in Instrumentation instance, create a ClassFileTransformer, and pass it to the Instrumentation instance. Below is an example:

package com.example.profiler;


import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;


public class Profiler implements ClassFileTransformer
{

protected Instrumentation instrumentation = null;

public static void premain(String agentArgs, Instrumentation inst)
{
System.out.println("premain");
Profiler profiler = new Profiler(inst);
}

public Profiler(Instrumentation inst)
{
instrumentation = inst;
instrumentation.addTransformer(this);
}

public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{
System.out.println("transform(" + className + ") (" + classfileBuffer.length + " bytes)");
return null;
}

}

Note that at this point we simply print the name and the size of the class passed to our transform method. Also note the Javadocs state that the method should return null if it chooses not to transform the class (returning the original classbyte array works, too). If I launch a simple "Hello, world!" program with this agent, I will see the following output:

premain
transform(HelloWorld) (1173 bytes)
Hello, world! 
Published at DZone with permission of Wayne Adams, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Eric Meallier replied on Tue, 2009/12/08 - 6:13am

hard to get this working !

 

during the instrumentation, a RuntimeException was throwed by getMethods() call. The problem comes from the naming convention of the classes.

The classname given by transform is like this test/Test. The classpool understand this syntax but store test.Test. When you are looking for the class (getClass() just before getMethods) the class is lazy loaded (the byte code is not introscepted) but is not good. the problem only appear when the getMethods is called.

A workaround is to call classPool.get(className.replace('/', '.'));

 

Thanks for the article.

Victor Tsoukanov replied on Fri, 2010/02/19 - 1:14am

If you do not want to pay money for profiling tool, there is a free and quite suitable profiler – Netbeans profiler

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.