Java NoClassDefFoundError несмотря на установленный путь к классу - PullRequest
8 голосов
/ 29 мая 2011

У меня возникли проблемы с запуском приложения Java в консоли и / или с Ant.Я знаю, что многие начальные проблемы связаны с тем, что classpath не задан или установлен неправильно, хотя я вполне уверен, что установил его правильно, поэтому мой поиск дал только результаты по этому вопросу.

Вот общеенастройка моего приложения: классы находятся в пакетах модель, вид и контроллер.controller.Controller - это класс с методом main.Я использую objectdb в качестве своего JPA-провайдера.

Я использую Ant для компиляции своего приложения.

После компиляции я могу запустить свое приложение из ant с помощью следующего скрипта:

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

где $ {main-class} - контроллер. Контроллер и classpath состоят из папок / lib и / dist (файл jar приложения скомпилирован в / dist)

Теперь я попытался скопировать все файлы .jarиз / lib и / dist в одну отдельную папку и запустите их с java -jar cooking.jar -cp ., что приведет к

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

Так что я попробовал ant и слегка измененную выше цель сборки:

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

что приводит к той же ошибке.Я не понимаю, почему.

Просто чтобы проверить это, я попытался запустить из командной строки, указав основной класс напрямую: java -cp . controller.Controller, который по какой-то причине не может даже найти класс (он там, я подтвердил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.

Я установил JAVA_HOME на путь моего JDK, а CLASSPATH на мой путь / lib JRE.ОС - Windows 7 64 бит, версия Java 1.6.0_25-b06

Я озадачен двумя вещами: а) Почему Java не может найти controller.Controller, даже если он присутствует в файле .jarа файл .jar находится в текущем каталоге?б) Что я делаю не так, что вызов Java с -jar, кажется, портит механизмы поиска.

Любая помощь очень ценится.

Ответы [ 3 ]

2 голосов
/ 29 мая 2011

Путь к классу должен состоять из

  1. каталогов с файлами классов (в соответствующем каталоге пакета)
  2. jar-файлов.

Вы не можете указатьпуть к классу к директории jar.Ситуация меняется при запуске сервера приложений (например, Tomcat), который загружает файлы jar из каталога для вас.

1 голос
/ 29 мая 2011

хотя я вполне уверен, что установил правильно

Доказательства против вас. JVM сообщает вам, что вы установили его неправильно.

Как вы думаете, на что указывает ref 'classpath'? Откуда вы думаете, что его значения берутся? Они должны быть определены внутри Ant build.xml, верно? Как это:

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

Если вы создаете исполняемый файл JAR, вам необходимо указать основной класс и путь к классам в манифесте, как правильно указал CoolBeans в комментарии. Расположение JAR сторонних производителей должно быть относительно исполняемого JAR. Вы должны упаковать их в свой исполняемый файл JAR таким образом, чтобы относительный путь был легко разобран и понят.

0 голосов
/ 22 ноября 2014

Я обнаружил, что это происходит, когда я указываю и <classpath> и jar="..." в цели. Я удалил jar="...", поместил .jar в список <classpath>, и он запустился после этого.

...