I'm trying to instrument an existing class with code that uses a generated 
class. I've prepared a small example to demonstrate what I mean and show you 
where I got stuck.

Assume the following class exists :


  | public class InstrumentMe {
  | 
  |     public InstrumentMe() {
  |         super();
  |     }
  | 
  |     public void printHelloWorld() {
  |         System.out.println("HelloWorld");
  |     }
  | }
  | 

The main-method in the class below generates a new class 'DynamicallyGenerated' 
on-the-fly and tries to instrument InstrumentMe#printHelloWorld() with a simple 
statement 'System.out.println(DynamicallyGenerated.class);'


  | import javassist.CannotCompileException;
  | import javassist.ClassPool;
  | import javassist.CtClass;
  | import javassist.CtMethod;
  | import javassist.CtNewClass;
  | import javassist.NotFoundException;
  | 
  | public final class AttemptGeneration {
  | 
  |     private AttemptGeneration() {
  |         super();
  |     }
  | 
  |     public static void main (String[] ignore) throws NotFoundException, 
CannotCompileException {
  |         ClassPool pool=ClassPool.getDefault();
  | 
  |         // step 1 : generate a new class
  |         String generatedName="DynamicallyGenerated";
  |         CtClass superclass=pool.get("java.lang.Object");
  |         CtNewClass generated = new CtNewClass(generatedName, pool, false, 
superclass);
  |         generated.toClass();
  |         // (*) see below : CtClass 
generatedClassAgain=pool.get(generatedName);
  | 
  |         // step 2 : try to load the generated class
  |         try {
  |             Class c = Class.forName(generatedName);
  |             System.out.println("class "+c.getName()+" loaded.");
  |         } catch (ClassNotFoundException e) {
  |             System.out.println("class "+generatedName+" not found");
  |             System.exit(1);
  |         }
  |         
  |         // step 3 : instrument an existing class to use the generated class
  |         CtClass instrumented = pool.get("InstrumentMe");
  |         CtMethod printHelloWorld = 
instrumented.getDeclaredMethod("printHelloWorld");
  |         String instrumentation = 
"System.out.println("+generatedName+".class);";
  |         
  |         // .. the line below causes a CannotCompileException
  |         printHelloWorld.insertAfter(instrumentation);
  |     }
  | }
  | 

The call to CtBehavior#insertAfter(String) in the last statement causes a 
CannotCompileException with the following stack trace :


  | Exception in thread "main" javassist.CannotCompileException: [source error] 
no such class: DynamicallyGenerated
  |     at javassist.CtBehavior.insertAfter(CtBehavior.java:613)
  |     at javassist.CtBehavior.insertAfter(CtBehavior.java:538)
  |     at AttemptGeneration.main(AttemptGeneration.java:40)
  | Caused by: compile error: no such class: DynamicallyGenerated
  |     at 
javassist.compiler.MemberResolver.searchImports(MemberResolver.java:406)
  |     at 
javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:382)
  |     at 
javassist.compiler.MemberResolver.lookupClassByJvmName(MemberResolver.java:310)
  |     at 
javassist.compiler.MemberResolver.resolveJvmClassName(MemberResolver.java:450)
  |     at 
javassist.compiler.MemberCodeGen.resolveClassName(MemberCodeGen.java:1064)
  |     at javassist.compiler.CodeGen.atClassObject(CodeGen.java:1546)
  |     at javassist.compiler.CodeGen.atExpr(CodeGen.java:1441)
  |     at javassist.compiler.ast.Expr.accept(Expr.java:67)
  |     at javassist.compiler.JvstCodeGen.atMethodArgs(JvstCodeGen.java:357)
  |     at 
javassist.compiler.MemberCodeGen.atMethodCallCore(MemberCodeGen.java:486)
  |     at javassist.compiler.MemberCodeGen.atCallExpr(MemberCodeGen.java:454)
  |     at javassist.compiler.JvstCodeGen.atCallExpr(JvstCodeGen.java:243)
  |     at javassist.compiler.ast.CallExpr.accept(CallExpr.java:45)
  |     at javassist.compiler.CodeGen.atStmnt(CodeGen.java:331)
  |     at javassist.compiler.ast.Stmnt.accept(Stmnt.java:49)
  |     at javassist.compiler.Javac.compileStmnt(Javac.java:558)
  |     at javassist.CtBehavior.insertAfter(CtBehavior.java:581)
  |     ... 2 more
  | 

Note that before the exception occurs, the output 'class DynamicallyGenerated 
loaded.' appears, which means that the generated class can be loaded by 
Class#forName(String).

I've stepped through some of the Javassist classes involved and noticed that 
the ClassPool doesn't seem to know the generated class. For example, when the 
statement marked with (*) is uncommented, it causes a NotFoundException with 
the following stack trace :

  | Exception in thread "main" javassist.NotFoundException: DynamicallyGenerated
  |     at javassist.ClassPool.get(ClassPool.java:389)
  |     at AttemptGeneration.main(AttemptGeneration.java:31)
  | 

The fact that the ClassPool doesn't know the generated class is a bit 
surprising, as its documentation mentions "...ClassPool objects hold all the 
CtClasses that have been created so that the consistency among modified classes 
can be guaranteed...". 

The javassist tutorial states "...A ClassPool object is a container of CtClass 
objects. Once a CtClass object is created, it is recorded in a ClassPool for 
ever. This is because a compiler may need to access the CtClass object later 
when it compiles source code that refers to the class represented by that 
CtClass....


So my question is why the above example doesn't work and how it can be made to 
work.

Thanks in advance for any help!


View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3944068#3944068

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3944068


-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user

Reply via email to