development

java.exe -jar로 내 jar를 실행하는 동안 NoClassDefFoundError가 발생했습니다… 무엇이 잘못 되었나요?

big-blog 2020. 12. 29. 08:23
반응형

java.exe -jar로 내 jar를 실행하는 동안 NoClassDefFoundError가 발생했습니다… 무엇이 잘못 되었나요?


더 쉬운 배포를 위해 항아리에 포장하려는 응용 프로그램이 있습니다. 응용 프로그램은 CLASSPATH에서 도달 할 수있는 클래스 집합으로 실행될 때 Windows cmd 창에서 잘 컴파일되고 실행됩니다. 그러나 클래스를 jar 업하고 동일한 cmd 창에서 java 1.6으로 실행하려고하면 예외가 발생하기 시작합니다.

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

재미있는 점은 잘못된 LogFactory가 지정된 클래스 경로에있는 commons-logging-1.1.jar에 있다는 것입니다. jar 파일 (예, 실제로 있습니다) :

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

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

네, 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 포함)로 복사 할 수있는 jar를 만들고 데이터베이스를 채우는 데 사용할 수있는 jar를 만드는 것입니다 (따라서 개발 환경과 배포 환경간에 클래스 경로가 다를 수 있음). 이 수수께끼에 대한 단서가 있으면 대단히 감사하겠습니다!


-jar 옵션은 -classpath와 상호 배타적입니다. 여기 에서 이전 설명을 참조 하십시오.

-항아리

Execute a program encapsulated in a JAR file. The first argument is the name of a JAR file instead of a startup class name. In order for this option to work, the manifest of the JAR file must contain a line of the form Main-Class: classname. Here, classname identifies the class having the public static void main(String[] args) method that serves as your application's starting point.

See the Jar tool reference page and the Jar trail of the Java Tutorial for information about working with Jar files and Jar-file manifests.

When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

A quick and dirty hack is to append your classpath to the bootstrap classpath:

-Xbootclasspath/a:path

Specify a colon-separated path of directires, JAR archives, and ZIP archives to append to the default bootstrap class path.

However, as @Dan rightly says, the correct solution is to ensure your JARs Manifest contains the classpath for all JARs it will need.


You can omit the -jar option and start the jar file like this:

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


This is the problem that is occurring,

if the JAR file was loaded from "C:\java\apps\appli.jar", and your manifest file has the Class-Path: reference "lib/other.jar", the class loader will look in "C:\java\apps\lib\" for "other.jar". It won't look at the JAR file entry "lib/other.jar".

Solution:-

  1. Right click on project, Select Export.
  2. Select Java Folder and in it select Runnable JAR File instead of JAR file.
  3. Select the proper options and in the Library Handling section select the 3rd option i.e. (Copy required libraries into a sub-folder next to the generated JAR).

[ EDIT = 3rd option generates a folder in addition to the jar, 2nd option ("Package required libraries into generated JAR") can also be used as you have the jar. ]

  1. Click finish and your JAR is created at the specified position along with a folder that contains the JARS mentioned in the manifest file.
  2. open the terminal,give the proper path to your jar and run it using this command java -jar abc.jar

    Now what will happen is the class loader will look in the correct folder for the referenced JARS since now they are present in the same folder that contains your app JAR..There is no "java.lang.NoClassDefFoundError" exception thrown now.

This worked for me... Hope it works for you too!!!


if you use external libraries in your program and you try to pack all together in a jar file it's not that simple, because of classpath issues etc.

I'd prefer to use OneJar for this issue.


i had the same problem with my jar the solution

  1. Create the MANIFEST.MF file:

Manifest-Version: 1.0

Sealed: true

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

Main-Class: com.MainClass

  1. Right click on project, Select Export.

select export all outpout folders for checked project

  1. select using existing manifest from workspace and select the MANIFEST.MF file

This worked for me :)


I have found when I am using a manifest that the listing of jars for the classpath need to have a space after the listing of each jar e.g. "required_lib/sun/pop3.jar required_lib/sun/smtp.jar ". Even if it is the last in the list.

ReferenceURL : https://stackoverflow.com/questions/250166/noclassdeffounderror-while-trying-to-run-my-jar-with-java-exe-jar-whats-wron

반응형