javassist loading a class file in the pre-main met

2020-08-09 10:01发布

问题:

I'm trying to load a specific class using javassist, I'm doing this inside a pre-main method as the follwoing:

public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                        ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException 
{
   byte[] byteCode = classfileBuffer;

   if(className.toLowerCase().endsWith("class1"))
   {
       ClassPool classPool = ClassPool.getDefault();
       CtClass ctClass = classPool.get("com.class2");
   }
}

but unfortuanetly, I'm getting a NotFoundException....

com.class2 is a class that will be loaded by the class loader after loading class1, but I nned to add a new method for class1 that has a return type of type com.class2

I tried all solutions inside stackoverflow.com but without any results.....

finally, both class1 and class2 are in the same package and inside the same JAR file, class1 has a member of type class2, but I have no idea why this classpool can't load the second one.

the stack trace here:

Exception: javassist.NotFoundException: com.Class2
 javassist.NotFoundException: com.Class2
at javassist.ClassPool.get(ClassPool.java:439)
at javassist.ClassPool.getCtClass(ClassPool.java:504)
at com.stuff.MainAppletTransformer.transform(MainAppletTransformer.java:69)
at sun.instrument.TransformerManager.transform(Unknown Source)
at sun.instrument.InstrumentationImpl.transform(Unknown Source)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.defineClassHelper(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.access$100(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
at sun.plugin2.applet.Plugin2Manager.initAppletAdapter(Unknown Source)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

回答1:

Your method does not have a return value and would therefore not compile. I can however still tell what is going wrong: You are not setting up a correct search path. From your stack trace, it seems like you are running an applet which is shielded by a specific ClassLoader. This class loader is not visible to Javassist in your current version.

By using ClassPool.getDefault(), you are looking up information from the system class path. For your applet, you would probably need to add the class loader that is handed over by the transformatio method as an argument.

You can append a class loader to Javassist's search path by

ClassPool classPool = ClassPool.getDefault();
classPool.appendClassPath(new LoaderClassPath(classLoader));

After appending this path, your example should work.