seelts seelts - 22 days ago 5
JSON Question

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.*

Also there are some other outer packages used in this class.

All this dependences are placed as jar files in my /path/to/libs/.

json-20160212.jar is among them.

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.

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.

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.

So, I can make conclusion, that it is the package org.json itself, that makes the problem.

What must I do, to make it work?

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:

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
.

Result is the same:
java.lang.NoClassDefFoundError: org/json/JSONException

Answer

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.
Without it, jar files must be extracted and that extracted content must be included to output.jar.