简体   繁体   中英

How do you include a class into the runtime environment when a custom classloader loaded the class?

I'm sure this seems obvious to most java programmers -- and I "think" I know the answer, but my issue is that I need to use a custom class loader. I'd like to use the custom class loader and still be able to use the classes in my code as I would any included class.

Example:

// returns my class loader -- set earlier on the thread.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class loadedVersion = Class.forName("org.example.MyClass"); // works
// loadedVersion's class loader is also equal to cl

// generates "java.lang.NoClassDefFoundError" at runtime on the following line
org.example.MyClass m = new org.example.MyClass();

How would I go about doing this so I can have the class loaded using the custom class loader, and still be able to use my classes "plainly" in the editor?

Edit: The revised title is misleading -- the classes load just fine. As indicated in my original post. The issue, my understanding, is that I am currently unable to use the classes in regular declaration statements (in the editor as I would use any java.* classes).

Update, I hope this better explains what I'm trying to do.

// set the thread's class loader
ClassLoader cloader = new MyClassLoader(); // internal mess to load bytecode omitted
Thread.currentThread().setContextClassLoader(cloader);

// This works:
Method m = cloader.loadClass("my.SuperClass").getMethod("doStaticMagic", new Class<?>[] {});
m.invoke(null, null);

// This does not work:
my.SuperClass.doStaticMagic(); // NoClassDefFoundError

This is the "issue". I want to use my classes "plainly" (I really don't know the right word) in the editor. I don't want to have to load each individual method -- isn't that what the classloader is for?

It would be better if you have only interface on classpath and loading the implementation by classloader or whatever, As in the code below:

Class loadedVersion = Class.forName("org.example.MyClass"); 

IMyClass m = (IMyClass)loadedVersion.newInstance();

where IMyClass is the interface which is implemented by org.example.MyClass . In this way you can absolutly decouple the implenetations of your classes from the client code

EDIT

NoClassDefFoundError is also arised when you have an exception while initializing static variables or executing static block initializer. Check youe class, maybe it throws such exceptions.

I think you want to use the newInstance() method . Since you have the "Class loadedVersion", you can use it to call the method.

Here is my solution (answer) to my original question. I still don't consider this ideal, but this does work.

I created a "bootstrap" application that first loads all the custom 3rd party jars, and then loads and calls my application class. This way I get auto-complete and source hints for the 3rd party jars.

I hope this helps someone, or invites further comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM