我有一个很小的Java程序“ Test.java”,它依赖于在同一目录的单独jar文件中找到的类“ TestLib”。
“项目”结构:
$ ls
Test.java Test.class testlib.jar
Test.java和testlib.jar是存根工件,再现了我在更大的应用程序中看到的类路径问题。 Test.java所做的只是从testlib.jar实例化一个类,然后退出:
import com.TestLib;
public class Test {
public static void main(String[] args) {
System.out.println("Before instantiating testlib");
new TestLib();
System.out.println("After instantiating testlib");
}
}
我的测试jar中有问题的测试库类:
$ unzip -l testlib.jar
...
com/TestLib.class
...
(此jar包含许多其他类和meta-inf文件,在此省略)
我可以使用javac Test.java -classpath .:testlib.jar
我尝试使用命令java -classpath .:testlib.jar Test
运行它,并获得输出:
Before instantiating testlib
Exception in thread "main" java.lang.NoClassDefFoundError: com/TestLib at Test.main(Test.java:6)
找不到“ TestLib”!
有趣的是,当我在Java调用中添加-verbose
标志时,我发现它甚至从未打开我的库jar在那寻找TestLib:
$ java -verbose -classpath .:testlib.jar Test 2>&1 | grep "Opened"
[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/rt.jar]
[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/jsse.jar]
[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/jce.jar]
由什么决定JVM是否打开jar文件以查找缺少的类?是否有任何META-INF或其他jar内容阻止JVM打开jar?我应该采取什么步骤解决为什么在运行时找不到“ TestLib”的问题?
答案 0 :(得分:0)
就我而言,由于我的JAR中存在META-INF/INDEX.LIST
文件,我看到了这种情况。
该文件(如果存在)包含JAR中可用的类文件列表。我的INDEX.LIST文件不完整,没有提及我的TestLib
类。因此,当ClassLoader进行查找时,他们相信INDEX.LIST
中的jar内容列表,并报告找不到该类。
((由于Gradle的“ shadow”插件的一些非常规(读取,错误)用法,我最终得到了一个不完整的INDEX.LIST
。默认情况下,shadow插件在构建有阴影的jar时会删除所有INDEX.LIST文件,但是我不小心将其配置为不执行此操作。因此,如果您在有阴影的jar中看到此行为,则可能是原因。)