Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java NoClassDefFoundError despite set classpath

I have some trouble with getting a Java application to run in the console and/or with Ant. I know that a lot of starting issues are related to the classpath being not set or incorrectly set, though I'm fairly sure I set it correctly, so my search only yielded results on that.

Here is the general setup of my application: classes are in packages model, view and controller. controller.Controller is the class with the main method. I am using objectdb as my JPA provider.

I am using Ant to compile my application.

After compiling, I can run my application from ant with the following script:

<target name="run" description="default build process">
    <java fork="true" classname="${main-class}">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

where ${main-class} is controller.Controller and classpath consists of /lib and /dist folders (the application's jar file is compiled to /dist)

Now I tried copying all .jar files from /lib and /dist to one separate folder and run them withjava -jar cooking.jar -cp . which results in

Exception in thread "main" java.lang.NoClassDefFoundError: javax/persistence/Persistence
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:28)
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:24)
    at controller.Controller.<init>(Controller.java:59)
    at controller.Controller.main(Controller.java:116)
Caused by: java.lang.ClassNotFoundException: javax.persistence.Persistence
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 4 more

So I tried ant and slightly modified above build target to:

<target name="run2" description="default build process">
    <java fork="true" jar="${dist.dir}/${ant.project.name}.jar">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

which results in the same error. I don't understand why.

Just to test it, I tried running from the command line by specifying the main class directly: java -cp . controller.Controller which for some reason cannot even locate the class (it's there, I confirmed it):

Exception in thread "main" java.lang.NoClassDefFoundError: controller/Controller
Caused by: java.lang.ClassNotFoundException: controller.Controller
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: controller.Controller.  Program will exit.

I have set JAVA_HOME to my JDK's path, and CLASSPATH to my JRE's/lib path. OS is Windows 7 64 bit, Java version is 1.6.0_25-b06

I am puzzled by two things: a) Why is Java unable to locate controller.Controller, even though it is present in the .jar file and the .jar file is in the current directory? b) What am I doing wrong that calling Java with -jar seems to mess up the lookup mechanisms.

Any help is highly appreciated.

like image 253
Tobias Avatar asked May 28 '11 20:05

Tobias


2 Answers

The class path should consist of

  1. directories with class files (in their proper package directory)
  2. jar files.

You cannot point the class path to a directory of jars. Things are different when running a application server (eg Tomcat), which will load jars from a directory for you.

like image 116
leblonk Avatar answered Nov 15 '22 00:11

leblonk


though I'm fairly sure I set it correctly

The evidence is against you. The JVM is telling you that you have not set it correctly.

What do you think that ref 'classpath' pointing to? Where do you assume its values are coming from? They should be defined inside the Ant build.xml, right? Like this:

<path id="production.class.path">
    <pathelement location="${production.classes}"/>
    <pathelement location="${production.resources}"/>
    <fileset dir="${production.lib}">
        <include name="**/*.jar"/>
        <exclude name="**/junit*.jar"/>
        <exclude name="**/*test*.jar"/>
    </fileset>
</path>

<path id="test.class.path">                            
    <path refid="production.class.path"/>
    <pathelement location="${test.classes}"/>
    <pathelement location="${test.resources}"/>
    <fileset dir="${test.lib}">
        <include name="**/junit*.jar"/>
        <include name="**/*test*.jar"/>
    </fileset>
</path>

If you're creating an executable JAR, you need to specify the main class and classpath in the manifest, as CoolBeans correctly pointed out in the comment. The 3rd party JAR locations have to be relative to the executable JAR. You should package them with your executable JAR in such a way that the relative path is easy to sort out and understand.

like image 32
duffymo Avatar answered Nov 14 '22 22:11

duffymo