Tracing class loading - 1.5 way

Java command line option -verbose:class may be used to trace class loading by JVM. But, this option does not print which class loader that loaded the class or protection domain or any other relevant information of interest. JDK 1.5 provides java.lang.Instrument package. While this package is meant to be used for load-time class file instrumentation purpose, we can use this to trace class loading.

File: ClassLoadTracer.java


import java.lang.instrument.\*;
import java.security.\*;

public class ClassLoadTracer {
	public static void premain(String agentArgs, Instrumentation inst) {
		final java.io.PrintStream out = System.out;
		inst.addTransformer(new ClassFileTransformer() {
			public byte[] transform(ClassLoader loader, String className,
		                 Class classBeingRedefined,
                		 ProtectionDomain protectionDomain,
		                 byte[] classfileBuffer) throws IllegalClassFormatException {

				out.print(className + " loaded by " + loader + " at " +
					new java.util.Date());
				out.println(" in " + protectionDomain);

                                // dump stack trace of the thread loading class 
                                Thread.dumpStack();

				// we just want the original .class bytes to be loaded!
				// we are not instrumenting it...
				return null;
			}
		});
	}
}

File: manifest.mf

Premain-Class: ClassLoadTracer

We can package the ClassLoadTracer as a jar file using the command:

   jar -cvfm tracer.jar manifest.mf ClassLoadTracer.class

Now, we can run any Java program with the following command
   java -javaagent:tracer.jar <MainClass> <arguments>
Sample output of running this against a hello program is below:
hello loaded by sun.misc.Launcher$AppClassLoader@133056f at Thu Jan 06 15:15:39
GMT+05:30 2005 in ProtectionDomain  (file:/E:/ )
 sun.misc.Launcher$AppClassLoader@133056f
 
 java.security.Permissions@35ce36 (
 (java.io.FilePermission \\E:\\- read)
 (java.lang.RuntimePermission exitVM)
)


java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java:1158)
        at ClassLoadTracer$1.transform(ClassLoadTracer.java:17)
        at sun.instrument.TransformerManager.transform(TransformerManager.java:122)
        at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:155)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
hello world

We can easily customize the above tracer code (for example, filter trace output based class loader type or class name pattern using a regular expression or protection domain and so on).

Comments:

I played around with that. How comes that not all classes are passed to the classfile tranformer? E.g. java.io.File (or java.lang.String or ... all this basic stuff). Neither Intrumentation.getAllLoadedClasses() called from premain() returns it nor gets it ever passed to transform(). And yes, I create a File object in my tests :) Do you have any ideas?

Posted by Ingo Maier on October 03, 2005 at 08:31 AM IST #

Yes, there are certain boostrap classes (preloaded) before any agent is loaded. transform() is not called for these classes.

Posted by A. Sundararajan on October 06, 2005 at 01:58 PM IST #

Can we fix the instructions regarding javaagent at: http://java.sun.com/developer/technicalArticles/releases/j2se15/#mnm Looks like the stuff has changed since this article was written ...

Posted by Kedar Mhaswade on July 12, 2006 at 01:25 AM IST #

Yeah, it's me again. Your instructions should be fixed: jar -cvfm tracer.jar manifest.mf ClassLoadTr\*.class and not jar -cvfm tracer.jar manifest.mf ClassLoadTracer.class

Posted by Kedar Mhaswade on July 12, 2006 at 01:30 AM IST #

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