繁体   English   中英

Java: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-assemblyOneJar之类的工具。

因此,解决方案:

据我了解,访问jar内jar文件内容的唯一方法是编写自己的类加载器。
没有它,必须提取jar文件,并且提取的内容必须包含在output.jar中。

暂无
暂无

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

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