views:

303

answers:

3

I want to launch a java subprocess, with the same java classpath and dynamically loaded classes as the current java process. The following is not enough, because it doesn't include any dynamically loaded classes:

String classpath = System.getProperty("java.class.path");

Currently I'm searching for each needed class with the code below. However, on some machines this fails for some classes/libs, the source variable is null. Is there a more reliable and simpler way to get the location of libs that are used by the current jvm process?

String stax     = ClassFinder.classPath("javax.xml.stream.Location");

public static String classPath(String qualifiedClassName) throws NotFoundException {
    try {
        Class qc = Class.forName( qualifiedClassName );
        CodeSource source = qc.getProtectionDomain().getCodeSource();
        if ( source != null ) {
            URL location = source.getLocation();        
            String f = location.getPath();
            f = URLDecoder.decode(f, "UTF-8"); // decode URL to avoid spaces being replaced by %20
            return f.substring(1);
        } else {
            throw new ClassFinder().new NotFoundException(qualifiedClassName+" (unknown source, likely rt.jar)");
        }
    } catch ( Exception e ) {
      throw new ClassFinder().new NotFoundException(qualifiedClassName);
    }
}
+2  A: 

See my previous question which covers getting the classpath as well as how to launch a sub-process.

Robert Petermeier
True - this is a similar question. What I need here are the additional dynamicaly loaded classes. I don't want to define an extra file with these or introduce extra environment variables to locate them, since they are all 'known about' by the current environment.
Edward Ross
A: 

If you look at the javadoc for Class.getClassLoader, you'll see that the "bootstrap" classloader is typically represented as the null. "String.class.getClassLoader()" will return null on the normal sun jvm implementations. i think this implementation detail carries over into the CodeSource stuff. As such, I wouldn't imagine you would need to worry about any class which comes from the bootstrap classloader as long as your sub-process uses the same jvm impl as the current process.

james
+1  A: 

I want to launch a java subprocess, with the same java classpath and dynamically loaded classes as the current java process.

You mean invoke a new JVM?

Given that...

  • it is possible to plug in all sorts of agents and instrumentation into a JVM that can transform classes at load time
  • it is possible to take a byte array and turn it into a class
  • it is possible to have complex class loader hierarchies with varying visibility between classes and have the same classes loaded multiple times

...there is no general, magic, catch-all and foolproof way to do this. You should design your application and its class loading mechanisms to achieve this goal. If you allow 3rd party plug-ins, you'll have to document how this works and how they have to register their libraries.

McDowell
In the end I uses the mechanism I describe above to find our library. Our library refers to the all the other libs in the manifest, which I know will be installed in the same folder as our library.
Edward Ross