IT이야기

항아리 안의 참조 항아리

cyworld 2021. 10. 13. 20:41
반응형

항아리 안의 참조 항아리


내용이 아래와 같은 항아리가 있습니다.

여기에 이미지 설명 입력

아래는 내 매니페스트 파일입니다.

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.7.0_06-b24 (Oracle Corporation)
Main-Class: org.sai.com.DerbyDemo
Class-Path: derby.jar derbyclient.jar derbynet.jar derbytools.jar

항아리를 실행하려고 할 때 ClassNotFoundExcception외부 항아리 내부의 항아리를 참조하지 않는다는 의미 를 던졌습니다 .

에서 Class-Path속성, 어떻게 항아리 (참조 할 수 있습니다 derby.jar실제 항아리 내부 등)?


이를 위해서는 사용자 정의 클래스 로더가 필요합니다 . One Jar를 살펴보십시오 .

One-JAR을 사용하면 종속성 Jar와 함께 Java 애플리케이션을 단일 실행 가능한 Jar 파일로 패키징할 수 있습니다.

그것은 건물을 단순화할 수 있는 개미 작업도 가지고 있습니다.

참조 ( 배경에서 )

대부분의 개발자는 종속 Jar 파일을 자체 Jar 파일에 넣고 META-INF/MANIFEST에 Class-Path 속성을 추가하면 트릭을 수행할 것이라고 합리적으로 가정합니다 .


jarname.jar
| /META-INF
| |  MANIFEST.MF
| |    Main-Class: com.mydomain.mypackage.Main
| |    Class-Path: commons-logging.jar
| /com/mydomain/mypackage
| |  Main.class
| commons-logging.jar

불행히도 이것은 작동하지 않습니다 . 자바Launcher$AppClassLoader는 이런 종류의Class-Path. 사용하려고 하는jar:file:jarname.jar!/commons-logging.jar것도 막다른 골목으로 이어집니다. 이 접근 방식은 지원하는 Jar 파일을 jarname.jar 파일이 설치된 디렉토리에 설치(즉, 분산)하는 경우에만 작동합니다.


당신은 할 수 없습니다. 로부터 공식 튜토리얼 :

매니페스트에서 Class-Path 헤더를 사용하면 애플리케이션을 실행하기 위해 Java를 호출할 때 긴 -classpath 플래그를 지정하지 않아도 됩니다.

참고: Class-Path 헤더는 JAR 파일 내의 JAR 파일이나 인터넷 프로토콜을 통해 액세스할 수 있는 클래스가 아니라 로컬 네트워크의 클래스 또는 JAR 파일을 가리킵니다. JAR 파일 내의 JAR 파일에 있는 클래스를 클래스 경로로 로드하려면 해당 클래스를 로드하는 사용자 정의 코드를 작성해야 합니다. 예를 들어, MyJar.jar에 MyUtils.jar이라는 다른 JAR 파일이 포함된 경우 MyJar.jar 매니페스트의 Class-Path 헤더를 사용하여 MyUtils.jar의 클래스를 클래스 경로로 로드할 수 없습니다.


Eclipse에는 실행 가능한 jar를 내보내는 옵션이 있습니다. 여기에 이미지 설명 입력모든 프로젝트 관련 항아리를 생성된 항아리에 패키징할 수 있는 옵션이 있으며 이 방법으로 Eclipse는 새 항아리 내에 통합된 항아리를 참조하는 사용자 정의 클래스 로더를 추가합니다.

여기에 이미지 설명 입력


클래스로더의 기본 구현은 jar-within-a-jar에서 로드할 수 없습니다. 이렇게 하려면 전체 'sub-jar'를 메모리에 로드해야 하며, 이는 jar 형식( 참조 보류 중 - 이를 지원하는 문서를 찾으면 수정하겠습니다.)

JarSplice 와 같은 프로그램을 사용하여 모든 것을 하나의 깨끗한 실행 가능한 jar 묶는 것이 좋습니다 .

편집: 소스 참조를 찾을 수 없지만 이 정확한 '문제'를 설명하는 Sun 웹 사이트의 해결되지 않은 RFE가 있습니다. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4648386

또한 \lib디렉터리의 하위 디렉터리에 라이브러리 jar 파일을 배치 classes한 다음 명령줄에서 실행 하여 프로그램이 작동하는지 '테스트'할 수 있습니다. 즉, 다음 디렉토리 구조를 사용합니다.

classes/org/sai/com/DerbyDemo.class
classes/org/sai/com/OtherClassFiles.class
classes/lib/derby.jar
classes/lib/derbyclient.jar

명령줄에서 위에서 언급한 'classes' 디렉터리로 이동하고 다음을 입력합니다.

java -cp .:lib/* org.sai.com.DerbyDemo

라이브러리에 jar 파일을 추가하고 (netbeans를 사용하는 경우) 매니페스트 파일 classpath을 다음과 같이 수정합니다 .

Class-Path: lib/derby.jar lib/derbyclient.jar lib/derbynet.jar lib/derbytools.jar

비슷한 답변이 여기에 있습니다.


사용자 정의 클래스 로더를 생성하지 않으려면. jar 파일 스트림을 읽습니다. 그리고 그것을 File 객체로 옮깁니다. 그런 다음 파일의 URL을 얻을 수 있습니다. URLClassLoader로 전송하면 jar 파일을 원하는 대로 로드할 수 있습니다. 견본:

InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("example"+ ".jar");
final File tempFile = File.createTempFile("temp", ".jar");
tempFile.deleteOnExit();  // you can delete the temp file or not
try (FileOutputStream out = new FileOutputStream(tempFile)) {
    IOUtils.copy(resourceAsStream, out);
}
IOUtils.closeQuietly(resourceAsStream);
URL url = tempFile.toURI().toURL();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});
urlClassLoader.loadClass()
...

Eclipse에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 RunAs -> Run Configuration을 선택하고 실행 구성을 저장하면 다음에 Runnable JAR로 내보낼 때 사용됩니다.

ReferenceURL : https://stackoverflow.com/questions/12357136/reference-jars-inside-a-jar

반응형