Исполняемый Jar с зависимостями

Я пытаюсь создать исполняемый файл jar из командной строки (я не хочу использовать ant или OneJar). Вот содержимое моего файла .jar:

jar tvf file.jar
     0 Mon Sep 20 17:16:12 CEST 2010 lib/
 45396 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.logging_1.0.4.v201005080501.jar
321330 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar
 55003 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar
     0 Mon Sep 20 19:15:00 CEST 2010 META-INF/
   265 Mon Sep 20 19:12:44 CEST 2010 META-INF/MANIFEST.MF
530609 Mon Sep 20 17:16:12 CEST 2010 ped.jar

содержимое META-INF/MANIFEST.MF:

Manifest-Version: 1.0
Class-Path: ped.jar lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar lib/org.apache.commons.logging_1.0.4.v201005080501.jar
Main-Class: fr.inserm.umr915.bomcat.ped.PedigreeDrawer

и ped.jar содержит основной класс

jar tvf ped.jar | grep PedigreeDrawer.class
 39541 Mon Sep 20 17:16:10 CEST 2010 fr/inserm/umr915/bomcat/ped/PedigreeDrawer.class

но когда я пытаюсь выполнить файл .jar, я получаю сообщение об ошибке:

java -jar file.jar
Exception in thread "main" java.lang.NoClassDefFoundError: fr/inserm/umr915/bomcat/ped/PedigreeDrawer
Caused by: java.lang.ClassNotFoundException: fr.inserm.umr915.bomcat.ped.PedigreeDrawer
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

Итак, я что-то упускаю здесь. Разве я не могу упаковать исполняемый файл jar, просто включив зависимости?

Спасибо за вашу помощь

Пьер


person Pierre    schedule 20.09.2010    source источник


Ответы (5)


Как уже упоминалось, банки в атрибуте Class-Path: относятся к расположению файла jar, а не внутри файла jar. Вероятно, это пережиток тех дней, когда Java предназначалась для запуска апплетов.

Вам нужно будет использовать такой инструмент, как maven uberjar, чтобы объединить все необходимые классы в одну банку, чтобы создать автономную исполняемую банку.

Конечно, вы также можете просто распаковать все jar-файлы в один каталог, добавить META-INF и манифест и снова заархивировать все, если вы абсолютно хотите избежать использования инструментов.

person Peter Tillemans    schedule 20.09.2010

что такое file.jar?
вы можете попробовать установить class-path следующим образом:

Class-Path: lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar lib/org.apache.commons.logging_1.0.4.v201005080501.jar

и запустите файл jar следующим образом:

java -jar ped.jar
person secmask    schedule 20.09.2010
comment
files.jar — это архив. Он содержит ped.jar и lib/*.jar , поэтому я не могу запустить java -jar ped.jar, если не извлеку его из архива (а я не хочу этого делать). - person Pierre; 20.09.2010

Вы не можете включить Jar внутрь Jar без специальной упаковки (например, OneJar и т. д.).

Если вы действительно не хотите использовать OneJar (или другие подобные инструменты), вам нужно будет включить несколько файлов Jar в свой дистрибутив.

person James Van Huis    schedule 20.09.2010

Значение «Class-Path» в вашем файле manifest.mf указывает ваш путь к классам, как если бы вы запускали свое приложение без параметра -jar, но с параметром -classpath lib/.... Пути интерпретируются локально, а не в вашем файле jar.

Альтернативой является использование one-jar или использование специального загрузчика классов, который просматривает jar файлы, содержащиеся в вашем внешнем файле jar.

С помощью JCL вы можете загружать свои классы непосредственно из встроенных jar-файлов следующим образом:

  JarClassLoader jcl=new JarClassLoader();
  jcl.add("myjar.jar"); // Add some class source

  jcl.getSystemLoader().setOrder(1); // Look in system class loader first
  jcl.getLocalLoader().setOrder(2); // if not found look in local class loader
  jcl.getParentLoader().setOrder(3); // if not found look in parent class loader
  jcl.getThreadLoader().setOrder(4); // if not found look in thread context class loader
  jcl.getCurrentLoader().setOrder(5); // if not found look in current class loader

  // A custom class loader that extends org.xeustechnologies.jcl.ProxyClassLoader
  MyLoader loader=new MyLoader();
  loader.setOrder(6);

  jcl.addLoader(loader); //Add custom loader

Но тогда вам нужно добавить jcl в свой путь к классам вместо этого... или добавить взорванный jcl в вашу банку.

person tangens    schedule 20.09.2010
comment
Так это означает, что весь архив file.jar должен быть извлечен, не так ли? - person Pierre; 20.09.2010

OneJar предназначен для решения такого рода проблем. Вы можете написать собственный загрузчик классов для того же эффекта.

person Jayan    schedule 20.09.2010