简体   繁体   中英

Not seeing any output when using a different classloader

So here's my issue:

I have some code that is being called when a certain event happens on a DocuShare server. I listen for the event in my own eventlistener. So far so good, this works without issue.

This listener will call other code that is developed separately and resides in its own jar file.

Currently we have the overhead of always having to shut down the entire system to deploy a new version of one of those jars so it can be used.

So now I am trying to create a system that copies that jarfile (not on the classpath) to another temp location (so no jarlock), loads the jarfile in its own different classloader and executes it. This way I can simply overwrite the original jarfile when a new version is developed. The code will then see if there was a modification to the jarfile and do the same steps if that's the case.

I have done this successfully in a simpler setup (a servlet being called) so I know the approach of 'hot deploying' the jars works.

However, in this case, the code works fine up until I start using the separate classloader. I can find the jarfile and check for differences and load the jarfile accordingly but when I try to access the class I don't get any output in System.out or System.err anymore. The code in the jar is not being executed properly but I can't see why.

Extra info: the code is being executed in its own Thread

Overview of whats happening:

  1. DocuShare sends an event
  2. My listener picks up the event
  3. The listener (implements java.util.concurrent.Executor) starts a new Thread (Runnable impl)
  4. The Runnable impl creates a new classloader and then checks if there is a new version of the jar file inside a folder, if so it will copy it to another dir, if not it uses the existing version, load it on the classpath of the new classloader and execute it
  5. Fromt the moment I load a class with the new ClassLoader I don't see any line printed in the System.out/System.err.

code example (in the Runnable.run() method):

URLClassLoader hotCL = new URLClassLoader(((URLClassLoader) systemCL).getURLs()); //new URLclassloader with URLs from system CL

//the following approach for putting the class on the classpath comes from another SO question from somebody else
Method m = cl.getClass().getDeclaredMethod("addURL", new Class[]{URL.class});
m.setAccessible(true);
m.invoke(cl, jar.toURI().toURL());
String cp = System.getProperty("java.class.path");
if (cp != null) {
    cp += File.pathSeparatorChar + jar.getCanonicalPath();
} else {
    cp = jar.toURI().getPath();
}

Logger.log(">>>>>>>> instantiating impl");  //this is printed in the System.out
Class<?> clsService = hotCL.loadClass(strService);  //strService is the class inside the separate jar
Object instance = clsService.newInstance();

Logger.log(">>>>>>>>>>>> class: " + clsService.getClass().toString()); //this is not printed in the System.out, neither is any log-statement after this or any error
//after this a method of the class instance is called but the code doesn't do anything.  Possibly an error but there's no error/stacktrace

Is there something I'm missing about ClassLoaders? I just don't get why I don't see any error or code being executed.

Your classloader is probably hanging when it tries to load JDK classes that are referenced from your dynamic classes, because it needs a parent classloader capable of loading JDK classes. You can borrow a functional parent from the current context, ie:

new URLClassLoader(urls, this.getClass().getClassLoader())

Check out this thread if you run into problems after reloading classes that have already been instantiated.

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