为什么 Java 找不到 CLASSPATH 中的 类?
Why is Java not finding classes that are in the CLASSPATH?
我正在尝试安装作为 .jar 安装程序分发的 Mooshak。当我 运行 文件时,它给了我以下关于丢失 class:
的错误
ifinlay@mooshak:~$ sudo java -jar MooshakInstaller.jar -cui
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/compress/archivers/ArchiveException
at pt.up.fc.dcc.mooshak.installer.Installer.<init>(Installer.java:26)
at pt.up.fc.dcc.mooshak.installer.Installer.main(Installer.java:52)
... 5 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.compress.archivers.ArchiveException
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:436)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 7 more
所以找不到 org/apache/commons/compress/archivers/ArchiveException class。但是我已经安装了这个库并且在我的 CLASSPATH 中有以下内容:
ifinlay@mooshak:~$ echo $CLASSPATH
.:/usr/share/maven-repo/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar
而且 CLASSPATH 中的这个 .jar 文件似乎确实包含有问题的 class:
ifinlay@mooshak:~$ jar tvf /usr/share/maven-repo/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar
# ... other classes edited out
722 Fri Mar 01 16:57:28 UTC 2019 org/apache/commons/compress/archivers/ArchiveException.class
# ... other classes edit out
那么为什么 Java 找不到这个 class 而它 似乎在路径中?任何帮助都会非常棒,我真的很抓狂。
感谢阅读!
编辑:.jar 的清单文件如下所示:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ junit.jar org.hamcrest.core_1.3.0.v201303031735.ja
r commons-compress-1.12.jar BrowserLauncher2-all-1_3.jar
Class-Path: .
Rsrc-Main-Class: pt.up.fc.dcc.mooshak.installer.Installer
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
所以这似乎暗示 commons-compress-1.12.jar 文件应该放在与安装程序相同的目录中。虽然这似乎不起作用...
Why is Java not finding classes that are in the CLASSPATH?
简短回答:因为它们不在实际的类路径中。
长答案:
安装程序有问题,或者您没有正确运行安装它/因为它被设计为运行。
当你 运行 java
像这样带有 -jar
选项时:
java -jar MooshakInstaller.jar -cui
它将忽略 CLASSPATH
变量,和 您添加的任何-cp
参数。这解释了为什么 Java 在您的(假设的)类路径上的 commons-compress-1.18.jar
JAR 文件中找不到 类。
这意味着以下之一:
MooshakInstaller.jar
安装程序缺少依赖项;即它坏了。 (我怀疑是这种情况。他们会发现这一点的。)
MooshakInstaller.jar
安装程序未设计为 运行 作为可执行 JAR。
MooshakInstaller.jar
安装程序期望在相对于 JAR 文件位置的某个位置找到依赖项。 (查看 JAR 的清单文件中是否有 "Class Path" 属性。)
我还会注意到,当你 运行 这个:
sudo java -jar MooshakInstaller.jar -cui
CLASSPATH
环境变量的值可能不会传递给根进程。检查 sudo
的手动输入。这不是这里的 实际 问题...因为 CLASSPATH
变量由于 -jar
选项而被忽略。
更新
看来您根本没有遵循 installation instructions:
To install Mooshak you must execute the following commands. Make sure your system has all requirements. Note that you must have root privileges
% tar xzf mooshak-version.tgz
% cd mooshak-version
% su
# ./install
那不是你做的,我强烈怀疑你实际做的不等同于上述。
(我不打算对此进行进一步调查,因为下载过程需要我向他们提供各种个人详细信息。何塞不行!)
此答案基于您提供的新信息。它改变了一切。
首先,我所说的 CLASSPATH
和 -jar
仍然是正确的。
然而,事实证明,Mooshak 2 安装程序是一个使用 "jar in jar" 加载程序的可执行 JAR。
- 主要class是
org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
。
清单指定安装程序的 class 路径应包括这些嵌套的 JAR,它们是安装程序 JAR 的一部分:
junit.jar
org.hamcrest.core_1.3.0.v201303031735.jar
commons-compress-1.12.jar
BrowserLauncher2-all-1_3.jar
JarRsrcLoader
入口点 classes 应该为上述 JAR 设置 classloader,然后启动安装程序。
它应该一切正常。
不过我确实看到了一件奇怪的事情。清单有 commons-compress-1.12.jar
,但您似乎正在尝试使用 commons-compress-1.18.jar
。
你说:
So this seems to imply that the commons-compress-1.12.jar file should just be placed in the same directory as the installer.
我不是那样看的,但我会看看能不能找到文档。
更新:没有。我找不到文档,但从 JarRsrcLoader
源代码看来,它不是那样工作的。
但我确实找到了线索。在 JarRsrcLoader
的当前版本中,Java 8 和 Java 9+ 有单独的代码。因此,如果 Mooshak 2.0 安装程序使用 JarRsrcLoader
的旧版本,并且您尝试使用 Java 9 或更高版本进行安装,那么 可能 它不行。
所以,请确保您使用 Java 8 ... 就像要求所说的那样。
但是,您在这里显然是想使用不同版本的压缩库。更好的方法是为 Mooshak 设置您自己的构建树:
... checkout the full source code with svn checkout https://svn.dcc.fc.up.pt/projects/Mooshak/Mooshak/
然后根据我认为在树中的说明修改依赖项并构建/安装。
我正在尝试安装作为 .jar 安装程序分发的 Mooshak。当我 运行 文件时,它给了我以下关于丢失 class:
的错误ifinlay@mooshak:~$ sudo java -jar MooshakInstaller.jar -cui
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/compress/archivers/ArchiveException
at pt.up.fc.dcc.mooshak.installer.Installer.<init>(Installer.java:26)
at pt.up.fc.dcc.mooshak.installer.Installer.main(Installer.java:52)
... 5 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.compress.archivers.ArchiveException
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:436)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 7 more
所以找不到 org/apache/commons/compress/archivers/ArchiveException class。但是我已经安装了这个库并且在我的 CLASSPATH 中有以下内容:
ifinlay@mooshak:~$ echo $CLASSPATH
.:/usr/share/maven-repo/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar
而且 CLASSPATH 中的这个 .jar 文件似乎确实包含有问题的 class:
ifinlay@mooshak:~$ jar tvf /usr/share/maven-repo/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar
# ... other classes edited out
722 Fri Mar 01 16:57:28 UTC 2019 org/apache/commons/compress/archivers/ArchiveException.class
# ... other classes edit out
那么为什么 Java 找不到这个 class 而它 似乎在路径中?任何帮助都会非常棒,我真的很抓狂。
感谢阅读!
编辑:.jar 的清单文件如下所示:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ junit.jar org.hamcrest.core_1.3.0.v201303031735.ja
r commons-compress-1.12.jar BrowserLauncher2-all-1_3.jar
Class-Path: .
Rsrc-Main-Class: pt.up.fc.dcc.mooshak.installer.Installer
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
所以这似乎暗示 commons-compress-1.12.jar 文件应该放在与安装程序相同的目录中。虽然这似乎不起作用...
Why is Java not finding classes that are in the CLASSPATH?
简短回答:因为它们不在实际的类路径中。
长答案:
安装程序有问题,或者您没有正确运行安装它/因为它被设计为运行。
当你 运行 java
像这样带有 -jar
选项时:
java -jar MooshakInstaller.jar -cui
它将忽略 CLASSPATH
变量,和 您添加的任何-cp
参数。这解释了为什么 Java 在您的(假设的)类路径上的 commons-compress-1.18.jar
JAR 文件中找不到 类。
这意味着以下之一:
MooshakInstaller.jar
安装程序缺少依赖项;即它坏了。 (我怀疑是这种情况。他们会发现这一点的。)MooshakInstaller.jar
安装程序未设计为 运行 作为可执行 JAR。MooshakInstaller.jar
安装程序期望在相对于 JAR 文件位置的某个位置找到依赖项。 (查看 JAR 的清单文件中是否有 "Class Path" 属性。)
我还会注意到,当你 运行 这个:
sudo java -jar MooshakInstaller.jar -cui
CLASSPATH
环境变量的值可能不会传递给根进程。检查 sudo
的手动输入。这不是这里的 实际 问题...因为 CLASSPATH
变量由于 -jar
选项而被忽略。
更新
看来您根本没有遵循 installation instructions:
To install Mooshak you must execute the following commands. Make sure your system has all requirements. Note that you must have root privileges
% tar xzf mooshak-version.tgz % cd mooshak-version % su # ./install
那不是你做的,我强烈怀疑你实际做的不等同于上述。
(我不打算对此进行进一步调查,因为下载过程需要我向他们提供各种个人详细信息。何塞不行!)
此答案基于您提供的新信息。它改变了一切。
首先,我所说的 CLASSPATH
和 -jar
仍然是正确的。
然而,事实证明,Mooshak 2 安装程序是一个使用 "jar in jar" 加载程序的可执行 JAR。
- 主要class是
org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
。 清单指定安装程序的 class 路径应包括这些嵌套的 JAR,它们是安装程序 JAR 的一部分:
junit.jar org.hamcrest.core_1.3.0.v201303031735.jar commons-compress-1.12.jar BrowserLauncher2-all-1_3.jar
JarRsrcLoader
入口点 classes 应该为上述 JAR 设置 classloader,然后启动安装程序。
它应该一切正常。
不过我确实看到了一件奇怪的事情。清单有 commons-compress-1.12.jar
,但您似乎正在尝试使用 commons-compress-1.18.jar
。
你说:
So this seems to imply that the commons-compress-1.12.jar file should just be placed in the same directory as the installer.
我不是那样看的,但我会看看能不能找到文档。
更新:没有。我找不到文档,但从 JarRsrcLoader
源代码看来,它不是那样工作的。
但我确实找到了线索。在 JarRsrcLoader
的当前版本中,Java 8 和 Java 9+ 有单独的代码。因此,如果 Mooshak 2.0 安装程序使用 JarRsrcLoader
的旧版本,并且您尝试使用 Java 9 或更高版本进行安装,那么 可能 它不行。
所以,请确保您使用 Java 8 ... 就像要求所说的那样。
但是,您在这里显然是想使用不同版本的压缩库。更好的方法是为 Mooshak 设置您自己的构建树:
... checkout the full source code with
svn checkout https://svn.dcc.fc.up.pt/projects/Mooshak/Mooshak/
然后根据我认为在树中的说明修改依赖项并构建/安装。