java.lang.ClassNotFoundException при запуске java -jar

Я использую ant для создания моего файла build.xml, он компилируется нормально, но затем получает среду выполнения java.lang.NoClassDefFoundError при запуске полученного файла jar через «java -jar my_jar.jar». Кажется, что это происходит много, но ни одно из решений связанных вопросов не помогло мне.

Мой путь к классам для javac содержит только "/usr/local/lib/libthrift.jar", а основной файл .java импортирует кучу бережливых пакетов, таких как org.apache.thrift.transport.TTransportException.

Когда я пытаюсь запустить программу через:

java -jar MyClass.jar

, получаю ошибку:

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.

Вот вещи, которые я пробовал до сих пор, но они не работают:

  • добавление флага в командную строку, например "java -cp /usr/local/lib/libthrift.jar -jar my_jar.jar", результат - та же ошибка, что и выше

  • добавление <attribute name="Class-Path" value="./:/usr/local/lib/libthrift.jar"/> внутрь тега manifest> моей банки приводит к той же ошибке, что и выше

  • добавление -Xbootclasspath/a:/usr/local/lib/libthrift.jar:./ в командную строку Java. он решает первую ошибку, но появляется другая ошибка:

    Исключение в потоке «основной» java.lang.NoClassDefFoundError: org/apache/log4j/Logger в org.apache.thrift.transport.TServerSocket.‹clinit›(TServerSocket.java:36) в MyClass.start(неизвестный источник) в MyClass .main(неизвестный источник)

ИЗМЕНИТЬ:

Если я закомментирую код, который создает экземпляры отсутствующих классов, но оставлю импорт, код будет выполняться нормально.

ИЗМЕНИТЬ:

Я переместил свои классы Java на сервер и сослался на MainClass с сервером в атрибуте манифеста, но это ничего не исправило.


person Heinrich Schmetterling    schedule 25.11.2009    source источник
comment
Просто добавил раздел Class-Path МАНИФЕСТА в свой ответ. Я только что видел ответ Джеймса Б., поэтому, если это сработает, вы можете выбрать его ответ в качестве официального.   -  person VonC    schedule 25.11.2009


Ответы (7)


Could not find the main class: MyClass

Ошибка, кажется, на самом деле связана с вашим MANIFEST, который:

Лучшее решение, когда у вас есть jar-файл, — попытаться включить требуемые jar-файлы в объявление манифеста.

Manifest-Version: 1.0 
Class-Path:  
 customer_client.jar  
 mailer_client.jar  
 signon_client.jar 
  • или может неадекватно определить MainClass в вашем 'my_jar.jar'.

См. это руководство:

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

<attribute name="Main-Class" value="howto.Hello"/> необходимо указать полный путь (пакеты) MainClass, а не только MainClass.

Если ваш основной класс находится в пакете по умолчанию (безымянный пакет), я не уверен, что на него может ссылаться загрузчик (см. этот ТАК вопрос)
Итак, переместите свой JarRunner в пакет и объявите его соответствующим образом в <attribute name="Main-Class" value="myPackage.JarRunner"/> элемент.

person VonC    schedule 25.11.2009
comment
Основной класс объявлен как класс JarRunner и находится в JarRunner.java в том же каталоге, что и build.xml. В моем манифесте атрибут выглядит так: имя атрибута=значение основного класса=JarRunner/> Это неправильно? - person Heinrich Schmetterling; 25.11.2009
comment
Я бы порекомендовал по крайней мере один пакет для размещения JarRunner вместо безымянного пакета - person VonC; 25.11.2009
comment
Если я добавлю свои java-файлы в пакет, а затем укажу MainClass как mypackage.JarRunner, он все равно не сможет найти класс. Это правильно? - person Heinrich Schmetterling; 25.11.2009
comment
Имеет ли это объяснение смысл, если учесть, что если я уберу отсутствующий код org.apache, но оставлю импорт, он будет работать нормально? - person Heinrich Schmetterling; 25.11.2009
comment
Да, так как Could not find the main class: MyClass фактически запускается тем фактом, что одна из его частей (класс apache) не найдена. Так что мой предыдущий комментарий здесь не поможет. - person VonC; 25.11.2009
comment
Я очень смущен сейчас. Я только что прошел учебник по манифесту, и я получаю ту же ошибку. Что я должен делать? - person Heinrich Schmetterling; 25.11.2009

Вам нужно указать все другие jar-файлы, которые требуются в вашем пути к классам в файле манифеста, прежде чем вы сможете выполнить java -jar my-test.jar, вот копия одного из моих файлов манифеста. Со всеми этими записями в манифесте я могу указать java -jar db_field_cleaner.jar, а все остальные банки встроены в путь к классам:

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

В качестве альтернативы используйте Maven, он намного лучше справляется с такими вещами!

person James B    schedule 25.11.2009

Вы сами дали ответ :-) добавьте все jar-файлы в свой путь к классам во время выполнения. Как вы сказали ранее, *.jar решил одну проблему, но регистраторы не могут это выяснить, поэтому добавьте log4j.jar в путь. В основном идея заключается в том, чтобы добавить все jar-файлы, необходимые для запуска, в путь к классам.

person GustyWind    schedule 25.11.2009

Параметры командной строки для java можно найти здесь.

Опции -jar и -cp/-classpath взаимоисключающие. Параметр -jar требует использования манифеста, и в этом файле должны быть перечислены относительные пути к зависимостям. Но, по сути, манифест является необязательным механизмом — вы можете указать необходимую информацию извне во время начальной загрузки. Если манифест вызывает у вас проблемы, не используйте его.

Я бы проверил, что вы нашли все свои зависимости с помощью такой команды:

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

Обратите внимание, что компилятор может успешно скомпилировать ваши классы, даже если все классы, которые могут потребоваться во время выполнения, отсутствуют. Компиляция пройдет успешно, если присутствуют прямые зависимости ваших классов. Зависимости ваших зависимостей не нужны для создания двоичного файла, и компилятор не будет проверять их без необходимости.

Сообщение о org/apache/log4j/Logger предполагает, что у вас отсутствует зависимость от log4j. Необходимо будет добавить эту библиотеку в путь к классам. Ознакомьтесь с документацией по библиотеке Thrift, чтобы определить ее зависимости.

person McDowell    schedule 25.11.2009

Ссылки на пути к классам в файле манифеста являются относительными ссылками. Просто для отладки вы можете скопировать все jar-файлы в то же место, что и my_jar.jar, и повторить попытку.

ссылка: http://www.rgagnon.com/javadetails/java-0587.html< /а>

person aldrin    schedule 25.11.2009

Вы можете попробовать добавить банки в домен сервера. У меня была похожая проблема, и это сработало для меня, когда я запускал ее на стеклянной рыбе. Я бы получил те не найденные исключения. Eclipse распознал его, и он скомпилировался нормально, но при запуске на сервере он не смог найти файл. Попробуйте добавить его в любой каталог lib, в котором установлен сервер.

person Randnum    schedule 16.12.2011

Это проблема, которая возникает,

если файл JAR был загружен из "C:\java\apps\appli.jar", и ваш файл манифеста имеет ссылку Class-Path: "lib/other.jar", загрузчик класса будет искать в "C:\java \apps\lib\" для "other.jar". Он не будет смотреть на запись файла JAR "lib/other.jar".

Решение:-

  1. Щелкните правой кнопкой мыши проект, выберите «Экспорт».
  2. Выберите папку Java и в ней выберите исполняемый файл JAR вместо файла JAR.
  3. Выберите правильные параметры и в разделе «Обработка библиотек» выберите третий вариант, т. Е. (Скопируйте необходимые библиотеки в подпапку рядом с созданным JAR).
  4. Нажмите «Готово», и ваш JAR будет создан в указанной позиции вместе с папкой, содержащей JARS, упомянутые в файле манифеста.
  5. откройте терминал, укажите правильный путь к вашей банке и запустите ее с помощью этой команды java -jar abc.jar

    Теперь произойдет то, что загрузчик классов будет искать в правильной папке JARS, на которые ссылаются, поскольку теперь они присутствуют в той же папке, которая содержит JAR вашего приложения. Теперь нет исключения «java.lang.NoClassDefFoundError».

Это сработало для меня... Надеюсь, это сработает и для вас!!!

person Gautam Mandsorwale    schedule 04.09.2012
comment
Ну, это работает, но я не думаю, что это то, что вы хотите. Преимущество исполняемого jar-файла должно заключаться в том, что это всего лишь один файл. Для вашего решения требуется другая папка. - person T3rm1; 06.08.2013