Instrumentation (Javaagent) and Javaassist, className Issue with getClassFile2

Published: 05/09/11 04:23 PM


Just a hint if you have the following problem:
You’re using javaassist (in my case 3.14.GA) and a Java-Agent / instrumentation to invoke javaassist for Class-transformations. (I use Java7 which works with Javaassist 3.14.GA).
The following code returns a CtClass:

//make sure to add your classpath, e.g. cp.appendClassPath(new LoaderClassPath(loader));
 
//throws no Exception
CtClass cc = cp.get(className);
 
//this would return a non-null object (alternative to above line of code)
//CtClass cc = cp.getOrNull(className);

But as soon as you invoke cc.getAnnotations or similar, it either fails silently (then add “catch (Exception e)” ) or (after you added the catch-block) you get a Runtime-Exception:

java.lang.RuntimeException: cannot find your/package/YourClassName: your.package.YourClassName found in your/package/YourClassName.class
	at javassist.CtClassType.getClassFile2(CtClassType.java:192)
	at javassist.CtClassType.getAnnotation(CtClassType.java:473)
	at your.package.Agent$1.transform(Agent.java:98)
	at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
	at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:794)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:144)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	...

Make sure to call ClassPool::get with a ClassName not containing slashes, but dots. That is:

instr.addTransformer(new ClassFileTransformer() {
  public byte[] transform(ClassLoader loader, String className, 
                                    Class classBeingRedefined, 
                                    ProtectionDomain protectionDomain, 
                                    byte[] classfileBuffer) 
                                        throws IllegalClassFormatException {
                        //NOT THAT WAY:
                        //CtClass cc = cp.get(className);
                        //BUT THAT WAY:
                        className = className.replace("/",".");
                        CtClass cc = cp.get(className);
...

Otherwise, ClassPool would happily populate your CtClass but it would fail on

//line 191 of CtClassType.java in javassist:javassist 3.14.GA
if (!cf.getName().equals(qualifiedName))

and throw an ugly Runtime-Exception, when you try to inspect Annotations.


Kommentieren Sie diesen Artikel

Maven, Netbeans Run and the use of a Javaagent

FindBugs Plugin for Netbeans