NoClassDefFoundError при попытке запустить мою банку с java.exe-jar...что случилось?


у меня есть приложение, которое я пытаюсь завернуть в банку для более легкого развертывания. Приложение компилируется и работает нормально (в окне cmd Windows) при запуске как набор классов, доступных из пути к классам. Но когда я поднимаю свои классы и пытаюсь запустить его с java 1.6 в том же окне cmd, я начинаю получать исключения:

C:devmyappsrccommondatagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:myapplibscommons -logging-1.1.jar -server -jar DataGen.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
    at java.net.URLClassLoader.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:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
    ... 1 more

самое смешное, что оскорбительный LogFactory, похоже, находится в commons-logging-1.1.jar, который находится в указанном пути к классу. Файл jar (да, это действительно там):

C:devmyappsrccommondatagen>dir C:myapplibscommons-logging-1.1.jar
 Volume in drive C is Local Disk
 Volume Serial Number is ECCD-A6A7

 Directory of C:myapplibs

12/11/2007  11:46 AM            52,915 commons-logging-1.1.jar
           1 File(s)         52,915 bytes
           0 Dir(s)  10,956,947,456 bytes free

содержание общего-ведение журнала-1.1.jar-файл:

C:devmyappsrccommondatagen>jar -tf C:myapplibscommons-logging-1.1.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/commons/
org/apache/commons/logging/
org/apache/commons/logging/impl/
META-INF/LICENSE.txt
META-INF/NOTICE.txt
org/apache/commons/logging/Log.class
org/apache/commons/logging/LogConfigurationException.class
org/apache/commons/logging/LogFactory.class
org/apache/commons/logging/LogFactory.class
org/apache/commons/logging/LogFactory.class
org/apache/commons/logging/LogFactory.class
org/apache/commons/logging/LogFactory.class
org/apache/commons/logging/LogFactory.class
... (more classes in commons-logging-1.1 ...)

да, commons-logging имеет класс LogFactory. И, наконец, содержание манифеста моей банки:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 10.0-b23 (Sun Microsystems Inc.)
Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest
Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink
 .jar GroboTestingJUnit-1.2.1-core.jar junit.jar

Это поставило меня в тупик, и любые коллеги, которых я прослушивал больше дня. Просто чтобы отбирать ответы, на данный момент, по крайней мере, сторонние решения для этого, вероятно, из-за лицензионных ограничений и политики компании (например: инструменты для создания exe или упаковка банок). Конечная цель-создать jar, который можно скопировать из окна моей разработки Windows на сервер Linux (с любыми зависимыми jar) и использовать для заполнения базы данных (поэтому пути к классам могут отличаться между средами разработки и развертывания). Любые подсказки к этой тайне будут очень признательны!

6 55

6 ответов:

параметр-jar является взаимоисключающим из-classpath. Смотрите старое описание здесь

-jar

выполнить программу, инкапсулированную в файл JAR. Первый аргумент - это имя файла JAR вместо имени класса запуска. Для того, чтобы эта опция работала, манифест jar-файл должен содержать строку из главных-форма класса: имя_класса. Здесь classname определяет класс, имеющий метод public static void main (String[] args это служит отправной точкой вашего приложения.

см. справочную страницу инструмента Jar и след Jar учебника Java для получения информации о работе с файлами Jar и манифестами Jar-файлов.

при использовании этого параметра файл JAR является источником всех пользовательских классов, а другие параметры пути к пользовательскому классу игнорируются.

быстрый и грязный хак, чтобы добавить свой classpath к bootstrap путь к классу:

- Xbootclasspath/a:путь

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

, а @Dan правильно говорит, правильное решение-обеспечить, чтобы ваш манифест JARs содержал путь к классам для всех банок, которые ему понадобятся.

вы можете опустить -jar опция и запустите файл jar следующим образом:

java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass

Это проблема, которая происходит,

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

решение:-

  1. щелкните правой кнопкой мыши проект, выберите Экспорт.
  2. выберите папку Java и в ней выберите запускаемый файл JAR вместо файла JAR.
  3. выберите нужные параметры и в разделе обработка библиотек выберите 3-й вариант, т. е. (скопируйте необходимые библиотеки в подпапку рядом с сгенерированной JAR).

[ EDIT = 3-й вариант генерирует папку в дополнение к jar, 2-й вариант ("пакет необходимых библиотек в сгенерированный JAR") также может быть использован, как у вас есть jar. ]

  1. Нажмите кнопку Готово и ваша банка будет создана на указанная позиция вместе с папкой, содержащей банки, упомянутые в файле манифеста.
  2. откройте терминал, укажите правильный путь к вашему jar и запустите его с помощью этой команды java-jar abc.банку

    теперь произойдет то, что загрузчик классов будет искать в правильной папке для указанных банок, так как теперь они присутствуют в той же папке, которая содержит вашу банку приложения..Нет "на Java.ленг.Noclassdeffounderror " исключение брошено сейчас.

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

Если вы используете внешние библиотеки в своей программе, и вы пытаетесь упаковать все вместе в файл jar, это не так просто, из-за проблем с classpath и т. д.

Я бы предпочел использовать OneJar по этому вопросу.

У меня была такая же проблема с моим фляги решение

  1. создать манифест.Файл MF:

Манифест-Версия: 1.0

опечатался: правда

Class-Path: . lib / jarX1.jar lib / jarX2.jar lib / jarX3.банку

основной класс: com.MainClass

  1. щелкните правой кнопкой мыши проект, выберите Экспорт.

выберите экспортировать все папки вывода для проверки проект

  1. выберите использование существующего манифеста из рабочей области и выберите манифест.MF file

Это сработало для меня :)

Я обнаружил, когда я использую манифест, что список jars для classpath должен иметь пробел после перечисления каждого jar, например " required_lib/sun / pop3.jar required_lib/sun / smtp.сосуд." Даже если он последний в списке.