ClassNotFoundException for class file on the classpath

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 acataly IS class file is in the given location, that is, this file exists:

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

      

Maybe the following is important: the code shown is executed in a javaagent attached to a jUnit test that I run programmatically (via Runtime.execute (...)) - so maybe something is beyond the obvious that could go wrong in background ... but still: if the classpath contains the class folder, then why can't it be loaded?

+2


source to share


3 answers


For anyone interested: I have no idea what the problem is.

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

I played around for a bit but finally gave up on looking for the "real" reason. Instead

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

      



Now I am using apache exec:

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

      

with the same String command, and suddenly it happens!

+1


source


The Java agent is loaded at the start of the JVM startup (for obvious reasons) and has its own "classpath" so it is not actually loaded by the system class loader (historically named). This is why you have "jarpath" as part of your command line argument.



SO you'll need something like System.getSystemClassLoader

, URLClassLoader.newInstance

(c java.class.path

) or Thread.getContextClassLoader

depending on your circumstances.

+4


source


You are assuming that if the target bytecode remains in the classpath, the corresponding class can be loaded by the current classloader. However, this is not the case if the current class is being loaded by the tricky / buggy class loader.

I suggest doing the following:

  • Check the classloader used:

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

  • Please provide a minimal but complete reproducible test case that illustrates the problem.

0


source







All Articles