[英]Java: NoClassDefFoundError: org/json/JSONException
So, I've spent the whole day with this problem. 因此,我整天都在解决这个问题。
I'm sure, that I'm using correct classpath. 我确定我使用的是正确的类路径。
Also, I have other packages as dependences, and they work perfectly. 另外,我还有其他软件包作为依赖项,它们可以完美地工作。
I have a class that uses org.json.* 我有一个使用org.json。*的类
Also there are some other outer packages used in this class. 另外,此类中还使用了其他一些外部软件包。
All this dependences are placed as jar files in my /path/to/libs/. 所有这些依赖关系都作为jar文件放在我的/ path / to / libs /中。
json-20160212.jar is among them. json-20160212.jar就在其中。
I'm compiling my sources with 我正在用
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
Compilation goes without issues. 编译没有问题。
Then, I'm creating jar from my class-files. 然后,我从类文件创建jar。
Manifest: 表现:
Main-Class: com.example.Source
Class-Path: /path/to/libs/json-20160212.jar
/path/to/libs/other.jar
/path/to/libs/another.jar
Command line: 命令行:
jar cfm output.jar manifest -C dst/ ./com
I'm getting jar with this manifest: 我得到这个清单的罐子:
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
As I've understood, this is ok for compiled manifest to have splitted lines. 据我了解,这对于已编译的清单具有分割行是可以的。
Now, I'm running my app from command line and get this error: 现在,我从命令行运行我的应用程序,并收到此错误:
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
As I know, that means, that org.json.JSONException was ok at compile time but missing at run time. 据我所知,这意味着org.json.JSONException在编译时可以,但在运行时会丢失。
But what must I do with this info? 但是我该怎么办?
I have that file. 我有那个文件。 It was at its place during compilation and at runtime.
它在编译期间和运行时都在它的位置。
Also there are other dependences, and their jars are also at that place. 另外还有其他依赖项,它们的罐子也在该位置。
If I remove JSON usage from my app, everything is working ok. 如果我从应用程序中删除JSON使用情况,则一切正常。
So, I can make conclusion, that it is the package org.json itself, that makes the problem. 因此,我可以得出结论,正是软件包org.json本身导致了问题。
What must I do, to make it work? 我必须怎么做才能使其正常工作?
UPDATE UPDATE
Now, I've made this changes: 现在,我进行了以下更改:
My directory structure: 我的目录结构:
libs/
json-20160212.jar
other.jar
another.jar
src/
com/
example/
Source.java
dst/
Manifest: 表现:
Main-Class: com.example.Source
Class-Path: libs/json-20160212.jar
libs/other.jar
libs/another.jar
Compilation: 汇编:
javac \
-cp "src/:libs/json-20160212.jar:libs/other.jar:libs/another.jar" \
-d dst/ \
src/com/example/Source.java
Jarchiving: Jarchiving:
jar cfm dst/output.jar manifest -C dst/ ./com ./libs
I'm getting jar with the structure as excepted: 我正在使用结构除外的罐子:
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/Source.class
libs/
libs/json-20160212.jar
libs/other.jar
libs/another.jar
And I'm running it with java -jar dst/output.jar
. 我正在使用
java -jar dst/output.jar
运行它。
Result is the same: java.lang.NoClassDefFoundError: org/json/JSONException
结果是相同的:
java.lang.NoClassDefFoundError: org/json/JSONException
The problem is your runtime classpath. 问题是您的运行时类路径。 There's no magic with this error.
这个错误是没有魔术的。 It quite simply means that org.json.JSONException is not on your runtime classpath.
这很简单地意味着org.json.JSONException不在您的运行时类路径上。 Find the jar that has this class in it and put it on your runtime classpath.
找到其中包含此类的jar,并将其放在您的运行时类路径中。
Note that the jars / classes needed for runtime are not necessarily the same as those needed for compiling. 请注意,运行时所需的jar /类不一定与编译所需的jar /类相同。 You quite often need more on your runtime classpath than your compile classpath.
在运行时类路径上比在编译类路径上经常需要更多的东西。 If JSONException isn't used explicitly in the code you are compiling, then it won't have to be on your compile classpath.
如果在要编译的代码中未明确使用JSONException,则不必在编译类路径中。 However, if one of the dependencies to your code needs JSONException and it's not on your runtime classpath, you will get a NoClassDefFoundError.
但是,如果代码的依赖项之一需要JSONException,并且不在运行时类路径中,则将出现NoClassDefFoundError。
One other issue that can possibly occur is that you have 2 different versions of the json jar on your classpath. 可能发生的另一个问题是,您的类路径上有2个不同版本的json jar。 Usually the first version of the class on the classpath gets loaded and the other ignored.
通常,类路径上的类的第一个版本会被加载,而另一个版本会被忽略。 If the first jar didn't have the version / signature of JSONException you needed in it but the second did, the correct class you would still get ignored, since it was further down on the classpath.
如果第一个jar没有所需的JSONException版本/签名,但第二个jar具有,则您仍将忽略正确的类,因为它在类路径中。
The issue would appear to be that you are not adding the dependent jars to your resultant jar. 问题似乎是您没有将依赖的jar添加到生成的jar中。
I have created a similar test jar, with the following structure (checking using jar tf)... 我创建了一个类似的测试jar,其结构如下(使用jar tf检查)...
META-INF/
META-INF /
META-INF/MANIFEST.MFMETA-INF / MANIFEST.MF
BeanIt.classBeanIt.class
TestBean.classTestBean.class
lib/LIB /
lib/opencsv-3.7.jarLIB / opencsv-3.7.jar
lib/commons-lang3-3.4.jarLIB /公地lang3-3.4.jar
My manifest... 我的清单...
Main-Class: BeanIt
主类:BeanIt
Class-Path: lib/opencsv-3.7.jar lib/commons-lang3-3.4.jar类路径:lib / opencsv-3.7.jar lib / commons-lang3-3.4.jar
In order to create this jar, you need to perform a command something similar to this... 为了创建这个罐子,您需要执行类似于此命令...
jar cfm App.jar MANIFEST.MF BeanIt.class TestBean.class lib
You can see that I've added my lib folder to the jar and referred to its contents on the classpath in the manifest. 您可以看到我已将我的lib文件夹添加到jar中,并在清单的类路径中引用了它的内容。
So, you can update your existing lib, like this... 因此,您可以像这样更新您现有的库...
jar uf App.jar path
Where path is the root path of your path/to/lib directory. 其中path是path / to / lib目录的根路径。 And it will simply add that to your jar.
它将简单地将其添加到您的jar中。
You can check your jar first using jar tf
, to see what it contains. 您可以先使用
jar tf
检查jar,以查看其包含的内容。
If you are still having difficulties getting it to work, then you can look at a "FAT JAR" solution whereby you expand all the internal jars classes and flatten them all out to a single JAR containing all the necessary classes. 如果仍然难以使它正常工作,那么可以看一下“ FAT JAR”解决方案,其中您可以扩展所有内部jars类并将它们全部展平为包含所有必需类的单个JAR。 They use decision mechanisms to deal with class conflicts in different JARs.
他们使用决策机制来处理不同JAR中的类冲突。 Tools such as sbt-assembly or OneJar may be what you need here, if you are unable to get your JAR working the way you expect.
如果无法使JAR正常工作,则可能需要sbt-assembly或OneJar之类的工具。
So, the solution: 因此,解决方案:
As I've understand, the only way to access the content of the jar files that are inside your jar, is to write your own class loader. 据我了解,访问jar内jar文件内容的唯一方法是编写自己的类加载器。
Without it, jar files must be extracted and that extracted content must be included to output.jar. 没有它,必须提取jar文件,并且提取的内容必须包含在output.jar中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.