2008-10-08 27 views

Respuesta

85

Si está intentando crear un único contenedor que contenga su aplicación y sus bibliotecas necesarias, existen dos formas (que yo conozco) de hacerlo. El primero es One-Jar, que utiliza un cargador de clases especial para permitir el anidamiento de jarras. El segundo es UberJar, (o Shade), que explota las bibliotecas incluidas y coloca todas las clases en el jar de nivel superior.

También debo mencionar que UberJar y Shade son complementos para Maven1 y Maven2, respectivamente. Como se menciona a continuación, también puede usar el complemento de ensamblaje (que en realidad es mucho más potente, pero mucho más difícil de configurar correctamente).

+64

Así que aquí estamos, 5 años después. Parece que esto sigue siendo cierto. Muy triste :( – T3rm1

+1

La mejor forma que conozco de hoy en día es usar el artefacto de jar IntelliJ. Extrae todas las clases de los frascos dependientes y los pone en su único frasco. – enl8enmentnow

+1

Eso no es posible en algunas situaciones como cuando su uso de implementaciones de JCE como BouncyCastle necesita ser firmado – debuti

6

No sin antes escribir su propio cargador de clases. Puede agregar archivos jar a classpath del jar, pero deben estar ubicados conjuntamente, no incluidos en el jar principal.

2

Necesita crear un cargador de clases personalizado para hacer esto o una biblioteca de terceros que admita esto. Su mejor opción es extraer el jar del tiempo de ejecución y agregarlo al classpath (o tenerlos ya agregados al classpath).

1

Estaba a punto de aconsejar extraer todos los archivos en el mismo nivel, luego hacer un jar del resultado, ya que el sistema del paquete debe mantenerlos perfectamente separados. Esa sería la forma manual, supongo que las herramientas indicadas por Steve lo harán muy bien.

2

Utilizo maven para mis compilaciones Java que tiene un complemento llamado maven assembly plugin.

Hace lo que su pregunta, pero al igual que algunas de las otras sugerencias describen - explosión esencialmente todos los frascos dependientes y recombinar en un solo frasco

+0

El plugin de ensamblaje Maven es bastante doloroso de usar ... UberJar y Shade son complementos Maven1 y Maven2 (un hecho que debería haber mencionado anteriormente , y lo hará ahora) –

49

usted no quiere utilizar esas soluciones "explotar contenidos JAR". Definitivamente hacen que sea más difícil ver cosas (ya que todo se explota en el mismo nivel). Además, podría haber conflictos de nombres (no deberían ocurrir si las personas usan paquetes adecuados, pero no siempre se puede controlar).

La característica que desea es una de las top 25 Sun RFEs: RFE 4648386, que Sun, en su sabiduría infinita, ha designado como de baja prioridad. Solo podemos esperar que Sun se despierte ...

Mientras tanto, la mejor solución que he encontrado (que desearía que Sun copiara en el JDK) es usar el cargador de clases personalizado JarClassLoader.

+4

En realidad, casi se garantiza que los conflictos de nomenclatura ocurran con cosas como configuración de log4j y textos de licencia. –

+1

Lamentablemente, JarClassLoader es GPLv3/comercial, por lo que probablemente no sea "copiado por sun (ahora oráculo)", y no se puede usar comercialmente a menos que tenga la influencia política interna y el tiempo para comprar algo. Estoy de acuerdo, sin embargo, que los jarros que barf en el directorio actual son algo malo. – Gus

+0

+1 para la idea en esta respuesta (aunque no responderé +1 a la respuesta): no puede volver a empaquetar ningún archivo JAR firmado, por lo que esta técnica no se puede usar en muchas situaciones (p. Ej. Java's 'activation.jar'). –

22

Usa el zipgroupfileset etiqueta (utiliza mismos atributos como un conjunto de archivos tag); Descomprimirá todos los archivos en el directorio y los agregará a su nuevo archivo. Más información: http://ant.apache.org/manual/Tasks/zip.html

Esta es una manera muy útil para evitar el problema jar-in-a-jar - Lo sé porque he buscado en Google esta pregunta exacta Stackoverflow al tratar de averiguar qué hacer. Si desea empaquetar un frasco o una carpeta de tarros en su un frasco construida con Ant, y luego olvidarse de todo esto ruta de clases o de terceros plug-in, todo lo que tienes que hacer es esto (en Ant):

<jar destfile="your.jar" basedir="java/dir"> 
    ... 
    <zipgroupfileset dir="dir/of/jars" /> 
</jar> 
+0

para mí funciona bien truco. – Lucke

8

Si está compilando con ant (estoy usando hormiga de eclipse), puede agregar los archivos jar adicionales diciéndole a la hormiga que los agregue ... No necesariamente el mejor método si tiene un proyecto mantenido por varias personas, pero funciona para un proyecto de una persona y es fácil.

por ejemplo, mi objetivo que estaba construyendo el archivo .jar fue:

<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}"> 
    <manifest> 
     <attribute name="Author" value="ntg"/> 
     ................................ 
     <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/> 
    </manifest> 
</jar> 

acabo añade una línea para que sea:

<jar ...."> 
    <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/> 
    <manifest> 
     ................................ 
    </manifest> 
</jar> 

donde estaba

<property name="external-lib-dir" value="C:\...\eclipseWorkspace\Filter\external\...\lib" /> 

la dir con los frascos externos. Y eso es todo ...

26

Después de algunas investigaciones, he encontrado un método que no requiere maven ni ninguna extensión o programa de terceros.

Puede usar "Class-Path" en su archivo de manifiesto.

Por ejemplo:

Crear MANIFIEST.MF archivo de manifiesto

Manifest-Version: 1.0 
Created-By: Bundle 
Class-Path: ./custom_lib.jar 
Main-Class: YourMainClass 

compilar todos sus clases y ejecutar jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

c stands para crear archivos f indica que desea especificar el archivo v es para entrada detallada m significa que vamos a pa archivo de manifiesto personalizado ss

Asegúrese de haber incluido el paquete lib in jar. Debería poder ejecutar jar de la manera normal.

basado en: http://www.ibm.com/developerworks/library/j-5things6/

resto de la información que necesita acerca de la clase de la ruta Qué encuentras here

+0

ver http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html – jntme

+0

Eso funciona muy bien. – Deian

+14

Esta respuesta no * funciona. desde el documento Oracle (vinculado por banana arriba): "El encabezado Class-Path apunta a clases o archivos JAR en la red local, no archivos JAR dentro del archivo JAR" – sebnukem

1

Bueno, hay una manera muy fácil si usted está utilizando Eclipse.

Exporte su proyecto como un archivo jar "ejecutable" (haga clic derecho en la carpeta del proyecto desde dentro de Eclipse, seleccione "Exportar ..."). Cuando configure los ajustes de exportación, asegúrese de seleccionar "Extraer las bibliotecas necesarias en el Jar generado". Tenga en cuenta, seleccione "Extraer ..." y no "Bibliotecas requeridas del paquete ...".

Además: Debe seleccionar una configuración de ejecución en la configuración de exportación. Entonces, siempre puedes crear un main() vacío en alguna clase y usarlo para tu configuración de ejecución.

De todos modos, no es garantizado para funcionar el 100% del tiempo - como se dará cuenta de un mensaje emergente que le indica que se asegure de comprobar las licencias de los archivos Jar que está incluyendo y sobre no copiando archivos de firma. Sin embargo, he estado haciendo esto por años y nunca he tenido un problema.

2

Si tiene eclpise IDE, solo necesita exportar su JAR y elegir "Paquetes de bibliotecas requeridas en el JAR generado". eclipse agregará automáticamente los JAR dependientes necesarios en el JAR generado y generará un cargador de clases personalizado de eclipse que cargue estos JAR automáticamente.

Cuestiones relacionadas