NoClassDefFoundError al intentar ejecutar mi archivo con java.exe -jar & # 8230; ¿qué ocurre?

StackOverflow https://stackoverflow.com/questions/250166

Pregunta

Tengo una aplicación que estoy tratando de envolver en un jar para una implementación más fácil. La aplicación compila y se ejecuta correctamente (en una ventana de cmd de Windows) cuando se ejecuta como un conjunto de clases a las que se puede acceder desde CLASSPATH. Pero cuando armo mis clases y trato de ejecutarlo con java 1.6 en la misma ventana de cmd, comienzo a obtener excepciones:

C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:\myapp\libs\commons -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$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: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

Lo curioso es que el LogFactory ofensivo parece estar en commons-logging-1.1.jar, que está en la ruta de clase especificada. El archivo jar (sí, realmente está ahí):

C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar
 Volume in drive C is Local Disk
 Volume Serial Number is ECCD-A6A7

 Directory of C:\myapp\libs

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

El contenido del archivo commons-logging-1.1.jar:

C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-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$1.class
org/apache/commons/logging/LogFactory$2.class
org/apache/commons/logging/LogFactory$3.class
org/apache/commons/logging/LogFactory$4.class
org/apache/commons/logging/LogFactory$5.class
org/apache/commons/logging/LogFactory.class
... (more classes in commons-logging-1.1 ...)

Sí, commons-logging tiene la clase LogFactory. Y finalmente, el contenido del manifiesto de mi frasco:

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

Esto me ha dejado perplejo, y todos los compañeros de trabajo que han molestado durante más de un día ahora. Solo para seleccionar las respuestas, al menos por ahora, las soluciones de terceros para esto probablemente no se realicen debido a las restricciones de licencia y las políticas de la compañía (por ejemplo, herramientas para crear exe o empaquetar frascos). El objetivo final es crear un archivo jar que pueda copiarse desde mi caja de Windows de desarrollo a un servidor Linux (con cualquier archivo jar dependiente) y usarlo para poblar una base de datos (por lo que las rutas de clase pueden ser diferentes entre los entornos de desarrollo e implementación). ¡Cualquier pista de este misterio sería muy apreciada!

¿Fue útil?

Solución

La opción -jar es mutuamente excluyente de -classpath. Consulte una descripción anterior aquí

  

-jar

     

Ejecuta un programa encapsulado en un archivo JAR. El primer argumento es el nombre de un archivo JAR en lugar de un nombre de clase de inicio. Para que esta opción funcione, el manifiesto del archivo JAR debe contener una línea del formulario Clase principal: nombre de clase. Aquí, el nombre de clase identifica la clase que tiene el método public static void main (String [] args) que sirve como punto de partida de su aplicación.

     

Consulte la página de referencia de la herramienta Jar y el rastro de Jar del Tutorial de Java para obtener información sobre cómo trabajar con archivos Jar y manifiestos de archivos Jar.

     

Cuando usa esta opción, el archivo JAR es la fuente de todas las clases de usuario, y se ignoran otras configuraciones de ruta de clase de usuario.

Un truco rápido y sucio es agregar tu ruta de clase a la ruta de clases de arranque:

  

-Xbootclasspath/a:path

     

Especifique una ruta separada por dos puntos de directires, archivos JAR y archivos ZIP para adjuntar a la ruta de la clase de arranque predeterminada.

Sin embargo, como dice correctamente @Dan , la solución correcta es asegurarse de que el Manifiesto de JARs contiene la ruta de clase para todos los JARs que necesitará.

Otros consejos

Puedes omitir la opción -jar e iniciar el archivo jar de esta manera:

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

Este es el problema que está ocurriendo,

si el archivo JAR se cargó desde " C: \ java \ apps \ appli.jar " ;, y su archivo de manifiesto tiene el Class-Path: reference " lib / other.jar " ;, el cargador de clases buscará " C: \ java \ apps \ lib \ " para " otro.jar " ;. No verá la entrada del archivo JAR " lib / other.jar " ;.

Solución:-

  1. Haga clic derecho en el proyecto, seleccione Exportar.
  2. Seleccione la carpeta Java y en ella seleccione el archivo JAR ejecutable en lugar del archivo JAR.
  3. Seleccione las opciones adecuadas y en la sección Manejo de bibliotecas, seleccione la tercera opción, es decir (Copie las bibliotecas requeridas en una subcarpeta junto al JAR generado).

[ EDIT = La tercera opción genera una carpeta además del jar, la segunda opción (" El paquete de bibliotecas requeridas en el JAR generado ") también se puede usar como usted tiene el jar. ]

  1. Haga clic en Finalizar y su JAR se creará en la posición especificada junto con una carpeta que contiene los JARS mencionados en el archivo de manifiesto.
  2. abre el terminal, dale la ruta correcta a tu jar y ejecútalo usando este comando java -jar abc.jar

    Ahora, lo que sucederá es que el cargador de clases buscará en la carpeta correcta para los archivos JAR referenciados, ya que ahora están presentes en la misma carpeta que contiene su aplicación JAR ... No hay " java.lang.NoClassDefFoundError " excepción lanzada ahora.

Esto me funcionó ... ¡Espero que también te funcione a ti!

si utiliza bibliotecas externas en su programa e intenta empaquetar todo en un archivo jar, no es tan sencillo, debido a problemas de classpath, etc.

Prefiero usar OneJar para este problema.

Tuve el mismo problema con mi tarro la solucion

  1. Cree el archivo MANIFEST.MF:
  

Versión de manifiesto: 1.0

     

Sellado: verdadero

     

Class-Path:. lib / jarX1.jar lib / jarX2.jar lib / jarX3.jar

     

Clase principal: com.MainClass

  1. Haga clic derecho en el proyecto, seleccione Exportar.
  

seleccione exportar todas las carpetas de salida para el proyecto verificado

  1. seleccione el manifiesto existente desde el área de trabajo y seleccione el archivo MANIFEST.MF

Esto me funcionó :)

Cuando estoy utilizando un manifiesto, he encontrado que la lista de archivos jar para el classpath necesita tener un espacio después de la lista de cada archivo jar, por ejemplo. " required_lib / sun / pop3.jar required_lib / sun / smtp.jar " ;. Incluso si es el último en la lista.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top