tags:

views:

259

answers:

3

Hello all!

I have the following code:

 // Test TODO remove
 try {
  System.out.println(System.getProperties().getProperty("java.class.path"));
  this.getClass().getClassLoader().loadClass("mypackage.MyClass");
 } catch (ClassNotFoundException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }

Now the output shows me, that the class is on the classpath, i.e.:

/...some/path.../workspace/project/target/test-classes:/rest/of/the/classpath
java.lang.ClassNotFoundException: mypackage.MyClass
        ...here be stacktrace...

I also made sure, that the class-file acutaly IS in the given location, i.e. this file exists:

/...some/path.../workspace/project/target/test-classes/mypackage/MyClass.class

Maybe the following is important: the shown code is executed in a javaagent attached to a jUnit test, that I start programtically (via Runtime.execute(...)) - so there is probably something beyond the obvious that can go wrong in the background... but still: if the classpath contains the folder with the class, how come it cannot be loaded?

A: 

You assume that if the target bytecode remains at classpath corresponding class can be loaded by the current class's class loader. However, that is not the case if current class is loaded by tricky/buggy class loader.

I'd suggest to do the following:

  1. Check used class loader:

    System.out.println(this.getClass().getClassLoader()); System.out.println(ClassLoader.getSystemClassLoader() == this.getClass().getClassLoader()); this.getClass().getClassLoader().loadClass("mypackage.MyClass");

  2. Provide minimal but complete reproducable test-case that illustrates the problem;

denis.zhdanov
Hello!Thanks for the idea, output:sun.misc.Launcher$AppClassLoader@24480457trueand a ClassLoader.getSystemClassLoader().loadClass("mypackage.MyClass");didn't help either...But thanks anyway. If nothing else helps I will have to opt for the test-case... which I avoided due to the effort involved.
roesslerj
+2  A: 

The Java agent is loaded early in starting the JVM (for obvious reasons) and has its own "classpath", so it isn't actually loaded by the (historically named) system class loader. That is why you have a 'jarpath' as part of the command line argument.

SO you will need something like System.getSystemClassLoader, URLClassLoader.newInstance (with java.class.path) or Thread.getContextClassLoader depending upon your circumstances.

Tom Hawtin - tackline
That intuitively and immiditately makes sense! Thanks already, I will investigate into that direction and state the results...
roesslerj
A: 

For all who are interested: I have no idea what the problem was.

I fiddled a bit with it, and it turned out that the command string that was executed by Runtime.exec(...) worked well if executed in the shell.

I fiddled a bit more, but finally gave up searching for the "real" reason. Instead of

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(command);

I now use apache exec:

CommandLine commandLine = CommandLine.parse(command);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(commandLine);

with the exact same command String, and all of a sudden it woks!

roesslerj