views:

1751

answers:

4

Hi folks, Is it possible to add a file (not necessarily a jar file) to java classpath at runtime. Specifically, the file already is present in the classpath, what I want is whether I can add a modified copy of this file to the classpath.

Thanks,

A: 

yes, you can. it will need to be in its package structure in a separate directory from the rest of your compiled code if you want to isolate it. you will then just put its base dir in the front of the classpath on the command line.

akf
A: 

Yes I believe it's possible but you might have to implement your own classloader. I have never done it but that is the path I would probably look at.

ssteidl
+1  A: 

You coud try java.net.URLClassloader with the url of the folder/jar where your updated class resides and use it instead of the default classloader when creating a new thread.

Tobias Schulte
+1  A: 

You can only add folders or jar files to a class loader. So if you have a single class file, you need to put it into the appropriate folder structure first.

Here is a rather ugly hack that adds to the SystemClassLoader at runtime:

import java.io.IOException;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;

public class ClassPathHacker {

private static final Class[] parameters = new Class[]{URL.class};

public static void addFile(String s) throws IOException {
   File f = new File(s);
   addFile(f);
}//end method

public static void addFile(File f) throws IOException {
   addURL(f.toURL());
}//end method


public static void addURL(URL u) throws IOException {

  URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
  Class sysclass = URLClassLoader.class;

  try {
     Method method = sysclass.getDeclaredMethod("addURL", parameters);
     method.setAccessible(true);
     method.invoke(sysloader, new Object[]{u});
  } catch (Throwable t) {
     t.printStackTrace();
     throw new IOException("Error, could not add URL to system classloader");
  }//end try catch

   }//end method

}//end class

The reflection is necessary to access the protected method addURL. This could fail if there is a SecurityManager.

Thilo
Thanks for the reply guys, I'm guessing we can also add a plain file (not a class or jar etc...) in the classpath, But how do I know which one would get picked up (the latest addition the the classpath or the old file)
Ah, that is a problem. Much of this is implementation dependent, so you should really not have to classes (or other resources) with the same name in the same classloader.
Thilo
If you put them into separate classloaders, then there is a spec. Usually the parent classloader takes precendence, for webapps it is sometimes the other way around (but still well-defined). The bootloader always comes first.
Thilo