java.lang.ClassNotFoundException when running java -jar
Asked Answered
P

7

5

I'm using ant to build my build.xml file, it compiles ok, but then getting a runtime java.lang.NoClassDefFoundError when running the resulting jar via "java -jar my_jar.jar". It seems like this comes up a lot but none of the related questions' solutions worked for me.

My classpath for javac contains only "/usr/local/lib/libthrift.jar" and the main .java file imports a bunch of thrift packages such as org.apache.thrift.transport.TTransportException.

When I try running the program via:

java -jar MyClass.jar

, I get the error:

Exception in thread "main" **java.lang.NoClassDefFoundError**: org/apache/thrift/transport/TTransportException
Caused by: java.lang.ClassNotFoundException: org.apache.thrift.transport.TTransportException
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: **MyClass**. Program will exit.

Here are the things I've tried so far that don't work:

  • adding a flag on the command line like "java -cp /usr/local/lib/libthrift.jar -jar my_jar.jar", the result is the same error as above

  • adding <attribute name="Class-Path" value="./:/usr/local/lib/libthrift.jar"/> inside my jar's manifest> tag, the result is the same error as above

  • adding -Xbootclasspath/a:/usr/local/lib/libthrift.jar:./ to the java command line. it solves the first error but a different error comes up:

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger at org.apache.thrift.transport.TServerSocket.<clinit>(TServerSocket.java:36) at MyClass.start(Unknown Source) at MyClass.main(Unknown Source)

EDIT:

If I comment out the code that instantiates the missing classes but leave the imports, the code executes fine.

EDIT:

I moved my java classes to a server and referenced the MainClass with the server in the manifest attribute, but that didn't fix anything.

Prady answered 25/11, 2009 at 8:29 Comment(1)
Just added the Class-Path section of the MANIFEST in my answer. I just saw James B's answer, so if this work, you could select his answer as the official one.Ramayana
R
9
Could not find the main class: MyClass

The error seems actually related to your MANIFEST which:

  • may not have a complete classpath Class-Path: see this HowTo

The best solution when you have a jar is to try to include the required jars into the manifest declaration.

Manifest-Version: 1.0 
Class-Path:  
 customer_client.jar  
 mailer_client.jar  
 signon_client.jar 
  • or may not define adequately the MainClass within your 'my_jar.jar'.

See this HowTo:

<target name="jar" depends="compile">
     <delete file="hello.jar"/>
     <delete file="MANIFEST.MF"/>
     <manifest file="MANIFEST.MF">
        <attribute name="Built-By" value="${user.name}"/>
        <attribute name="Main-Class" value="howto.Hello"/>
    </manifest>

      <jar destfile="hello.jar"
           basedir="."
           includes="**/*.class"
           manifest="MANIFEST.MF"
           />
  </target>

the <attribute name="Main-Class" value="howto.Hello"/> needs to specify the full path (packages) of the MainClass, not just MainClass.

If your main class is in the default package (the unnamed package), I am not sure it can be referenced by the loader (see this SO question)
So move your JarRunner into a package, and declare it appropriately in the <attribute name="Main-Class" value="myPackage.JarRunner"/> element.

Ramayana answered 25/11, 2009 at 8:33 Comment(6)
The main class is declared as class JarRunner and is in JarRunner.java in the same directory as build.xml. In my manifest, the attribute looks like: attribute name="Main-Class" value="JarRunner"/> Is this wrong?Prady
I would recommend at least one package to put JarRunner into, instead of the "unnamed package"Ramayana
If I add my java files to a package and then specify the MainClass as mypackage.JarRunner it still can't find the class. Is this the right thing?Prady
Does this explanation make sense when considering that if I take away the missing org.apache code but leave the imports, it runs ok?Prady
Yes it does, since the Could not find the main class: MyClass is actually triggered by the fact one of its part (the apache class) is not found. So my previous comment do not help here.Ramayana
I'm very confused now. I just went through the manifest tutorial and I'm getting the same error. What should I actually do?Prady
D
4

You need to specify all the other jars that are required in your classpath in the manifest file before you can execute java -jar my-test.jar, here is a copy of one of my manifest files. With all these entries in the manifest I can specify java -jar db_field_cleaner.jar and all the other jars are inlined into the classpath :

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: James B
Build-Jdk: 1.6.0_01
Package: com.blah.dbfieldcleaner
Specification-Title: db_field_cleaner
Specification-Version: 2.5.7-SNAPSHOT
Implementation-Title: db_field_cleaner
Implementation-Version: 2.5.7-SNAPSHOT
Implementation-Vendor-Id: com.blah.dbfieldcleaner
Implementation-Vendor:
Main-Class: com.blah.dbfieldcleaner.main.Main
mode: development
url: ..\..\db_field_cleaner\target\site
Class-Path: log4j-1.2.14.jar cygna_commons-2.5.7-SNAPSHOT.jar mail-1.4
 .jar activation-1.1.jar jdic-0.9.5.jar jdic_native-0.9.5.jar jdic_plu
 s-0.2.2.jar jdic_plus_native-0.2.2.jar jtds-1.2.2.jar xstream-1.3.1.j
 ar xpp3_min-1.1.4c.jar commons-net-2.0.jar text_processing-2.5.7-SNAP
 SHOT.jar

Alternatively, use Maven, it's loads better at this kind of stuff!

Diagnose answered 25/11, 2009 at 9:10 Comment(0)
J
1

You had given answer yourself :-) add all the jars to your runtime classpath.As you said earlier *.jar solved one problem but loggers are not able to find out, so add log4j.jar to the path. Basically the idea is add all the jars required for running in to classpath.

Jessiajessica answered 25/11, 2009 at 8:36 Comment(0)
P
1

The command line options for java can be found here.

The -jar and -cp/-classpath options are mutually exclusive. The -jar option requires the use of a manifest and the relative paths to dependencies should be listed in this file. But essentially, the manifest is an optional mechanism - you can specify the required information externally at bootstrap time. If the manifest is causing you problems, don't use one.

I would test that you have you have located all your dependencies with a command like this:

java -cp /usr/local/lib/libthrift.jar:my_jar.jar  MyClass

Note that the compiler may successfully compile your classes even if all the classes that might be required at runtime are not present. Compilation will succeed if the direct dependencies of your classes are present. The dependencies of your dependencies are not necessary to create the binary and the compiler will not inspect them needlessly.

The message about org/apache/log4j/Logger suggests that you have a missing dependency on log4j. It will be necessary to add this library to the classpath. Check the documentation for the Thrift library to determine its dependencies.

Paraformaldehyde answered 25/11, 2009 at 9:58 Comment(0)
A
1

This is the problem that is occurring,

if the JAR file was loaded from "C:\java\apps\appli.jar", and your manifest file has the Class-Path: reference "lib/other.jar", the class loader will look in "C:\java\apps\lib\" for "other.jar".  It won't look at the JAR file entry "lib/other.jar".

Solution:-

  1. Right click on project, Select Export.
  2. Select Java Folder and in it select Runnable JAR File instead of JAR file.
  3. Select the proper options and in the Library Handling section select the 3rd option i.e. (Copy required libraries into a sub-folder next to the generated JAR).
  4. Click finish and your JAR is created at the specified position along with a folder that contains the JARS mentioned in the manifest file.
  5. open the terminal,give the proper path to your jar and run it using this command java -jar abc.jar

    Now what will happen is the class loader will look in the correct folder for the referenced JARS since now they are present in the same folder that contains your app JAR..There is no "java.lang.NoClassDefFoundError" exception thrown now.

This worked for me... Hope it works you too!!!

Acquiesce answered 4/9, 2012 at 12:29 Comment(1)
Well this works but I don't think this is what you want. The advantage of a runnable jar should be that it is only one file. Your solution requires another folder.Kamerad
E
0

The class path references in the manifest file are relative refs. Just to debug, you might want to copy all the jars into the same location as my_jar.jar and attempt it again.

reference : http://www.rgagnon.com/javadetails/java-0587.html

Eijkman answered 25/11, 2009 at 10:30 Comment(0)
U
0

You might try adding the jars to the domain of the server. I had a similar problem and this worked for me when I was running it on glassfish. I would get those not found exceptions. Eclipse recognized it and it compiled fine but when ran on the server it couldn't find the file. Try adding it to whatever lib directory the server is installed to.

Uranometry answered 16/12, 2011 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.