简体   繁体   English

类路径上的类文件的ClassNotFoundException

[英]ClassNotFoundException for class file on 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, ie: 现在输出显示出该类位于类路径上,即:

/...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, ie 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? 也许以下几点很重要:所示代码是在附加到jUnit测试的javaagent中执行的,我通过编程方式启动了该代码(通过Runtime.execute(...))-因此,很明显,除了背景...但仍然:如果类路径包含带有类的文件夹,那么为什么它不能被加载?

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. Java代理在启动JVM的早期就被加载(出于明显的原因),并且具有自己的“类路径”,因此(历史名称)系统类加载器实际上并未加载它。 That is why you have a 'jarpath' as part of the command line argument. 这就是为什么在命令行参数中包含“ jarpath”的原因。

SO you will need something like System.getSystemClassLoader , URLClassLoader.newInstance (with java.class.path ) or Thread.getContextClassLoader depending upon your circumstances. Thread.getContextClassLoader根据您的情况,您将需要诸如System.getSystemClassLoaderURLClassLoader.newInstance (带有java.class.path )或Thread.getContextClassLoader类的东西。

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. 我对此进行了一些摆弄,结果发现,如果在shell中执行,则Runtime.exec(...)执行的命令字符串可以很好地工作。

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: 我现在使用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! 使用完全相同的命令String,突然间它醒了!

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 the 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 reproducible test-case that illustrates the problem 提供最小但完整的可再现的测试用例来说明问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM