![](/img/trans.png)
[英]Intellij Java: java.lang.NoClassDefFoundError: org/json/JSONException
[英]Java: NoClassDefFoundError: org/json/JSONException
因此,我整天都在解决这个问题。
我确定我使用的是正确的类路径。
另外,我还有其他软件包作为依赖项,它们可以完美地工作。
我有一个使用org.json。*的类
另外,此类中还使用了其他一些外部软件包。
所有这些依赖关系都作为jar文件放在我的/ path / to / libs /中。
json-20160212.jar就在其中。
我正在用
javac \
-cp "src/:/path/to/libs/json-20160212.jar:/path/to/libs/other.jar:/path/to/libs/another.jar" \
-d dst/ \
src/com/example/Source.java
编译没有问题。
然后,我从类文件创建jar。
表现:
Main-Class: com.example.Source
Class-Path: /path/to/libs/json-20160212.jar
/path/to/libs/other.jar
/path/to/libs/another.jar
命令行:
jar cfm output.jar manifest -C dst/ ./com
我得到这个清单的罐子:
Manifest-Version: 1.0
Class-Path: /path/to/libs/json-20160212.jar /path/to/libs/other.jar /p
ath/to/libs/another.jar
Created-By: 1.7.0_101 (Oracle Corporation)
Main-Class: com.example.Source
据我了解,这对于已编译的清单具有分割行是可以的。
现在,我从命令行运行我的应用程序,并收到此错误:
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: org/json/JSONException
at com.example.Source.run(Source.java:30)
Caused by: java.lang.ClassNotFoundException: org.json.JSONException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 1 more
据我所知,这意味着org.json.JSONException在编译时可以,但在运行时会丢失。
但是我该怎么办?
我有那个文件。 它在编译期间和运行时都在它的位置。
另外还有其他依赖项,它们的罐子也在该位置。
如果我从应用程序中删除JSON使用情况,则一切正常。
因此,我可以得出结论,正是软件包org.json本身导致了问题。
我必须怎么做才能使其正常工作?
UPDATE
现在,我进行了以下更改:
我的目录结构:
libs/
json-20160212.jar
other.jar
another.jar
src/
com/
example/
Source.java
dst/
表现:
Main-Class: com.example.Source
Class-Path: libs/json-20160212.jar
libs/other.jar
libs/another.jar
汇编:
javac \
-cp "src/:libs/json-20160212.jar:libs/other.jar:libs/another.jar" \
-d dst/ \
src/com/example/Source.java
Jarchiving:
jar cfm dst/output.jar manifest -C dst/ ./com ./libs
我正在使用结构除外的罐子:
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/Source.class
libs/
libs/json-20160212.jar
libs/other.jar
libs/another.jar
我正在使用java -jar dst/output.jar
运行它。
结果是相同的: java.lang.NoClassDefFoundError: org/json/JSONException
问题是您的运行时类路径。 这个错误是没有魔术的。 这很简单地意味着org.json.JSONException不在您的运行时类路径上。 找到其中包含此类的jar,并将其放在您的运行时类路径中。
请注意,运行时所需的jar /类不一定与编译所需的jar /类相同。 在运行时类路径上比在编译类路径上经常需要更多的东西。 如果在要编译的代码中未明确使用JSONException,则不必在编译类路径中。 但是,如果代码的依赖项之一需要JSONException,并且不在运行时类路径中,则将出现NoClassDefFoundError。
可能发生的另一个问题是,您的类路径上有2个不同版本的json jar。 通常,类路径上的类的第一个版本会被加载,而另一个版本会被忽略。 如果第一个jar没有所需的JSONException版本/签名,但第二个jar具有,则您仍将忽略正确的类,因为它在类路径中。
问题似乎是您没有将依赖的jar添加到生成的jar中。
我创建了一个类似的测试jar,其结构如下(使用jar tf检查)...
META-INF /
META-INF / MANIFEST.MF
BeanIt.class
TestBean.class
LIB /
LIB / opencsv-3.7.jar
LIB /公地lang3-3.4.jar
我的清单...
主类:BeanIt
类路径:lib / opencsv-3.7.jar lib / commons-lang3-3.4.jar
为了创建这个罐子,您需要执行类似于此命令...
jar cfm App.jar MANIFEST.MF BeanIt.class TestBean.class lib
您可以看到我已将我的lib文件夹添加到jar中,并在清单的类路径中引用了它的内容。
因此,您可以像这样更新您现有的库...
jar uf App.jar path
其中path是path / to / lib目录的根路径。 它将简单地将其添加到您的jar中。
您可以先使用jar tf
检查jar,以查看其包含的内容。
如果仍然难以使它正常工作,那么可以看一下“ FAT JAR”解决方案,其中您可以扩展所有内部jars类并将它们全部展平为包含所有必需类的单个JAR。 他们使用决策机制来处理不同JAR中的类冲突。 如果无法使JAR正常工作,则可能需要sbt-assembly或OneJar之类的工具。
因此,解决方案:
据我了解,访问jar内jar文件内容的唯一方法是编写自己的类加载器。
没有它,必须提取jar文件,并且提取的内容必须包含在output.jar中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.