Not able to use reflection to invoke method on a Class from different Classloader
vikrammurugesan Mar 26, 2014 11:13 AMI am migrating my application from EAP 5.1.2 to EAP 6.0.1 (waiting for 6.2.0 to be approved by my company).
Version Details - EAP 6.0.1, Windows x86 JDK 1.7.0_45
We have this logic in our code (EAR artifact) that,
- Creates a custom classloader and loads some jars needed into this classloader (it just add all the classes in these jars into the classloader).
- Sets the TCCL (thead context class loader) to this custom classloader.
- Looks up a specific class from this custom classloader and invokes a method in the class using Reflection.
- To invoke the method it passes one of the classes from the Application's module classloader as parameter.
- After invoking we set the TCCL back to its original classloader.
We have to do the 5 step logic I mentioned above several times during runtime. And the JARs are different each time.
Step 4 is where the problem arises. Due to the modular classloader design, in EAP 6, the code is not able to invoke this method (because the parameter is of type org.omg.CORBA.portable.InputStream - which is loaded by the JacORB module classloader). It throws IllegalArgumentException saying I'm trying to pass the parameter from the wrong Classloader.
Things I have tried so far,
- I tried putting the JacORB classes in my project - assuming my app would load the jacorb classes from the app, but I was wrong and I realized I did not understand the classloader design. So I read the Class Loading in AS7 - JBoss AS 7.0 - Project Documentation Editor - which clearly explains why.
- I tried cloning my java.lang.reflect.Method instance using the transloader API to the app classloader. Unfortuntely transloader can only clone objects that are Seriallizable and java.lang.reflect.Method is not.
- I tried cloning my paramter of type org.omg.CORBA.portable.InputStream to the custom classloader (TCCL) and again transloader is not able to do it. It is probably a bug in the transloader API and the last time it was updated is 2007. I tried to fix the problems in the transloader project and after I got it working, I was back to square one, It gave the same IllegalArgumentException. So it did not help much
- I tried adding the JARs to the System Classloader using this technique. Again my App Class loader is not able to load those classes that I added using this technique. I had a look at how the JBoss ModuleClassLoader loads classes and I think the ModuleClassloader will not lookup classes from the URLs I added. Please correct me if I am wrong as I am not very confident about this. Also if there is a way to make the App ModuleClassLoader look up classes from URLs available in System classloader.
- I tried creating my own JBoss module. It worked but so it is not a workable solution as I have to change the JARs frequently during runtime
As you can seen I have spent the past few days trying to overcome this problem with a solution. I would greatly appreciate any help or ideas.
Thanks,
Vikram