JAR 내의 JAR을 포함하는 클래스 경로


134

classpath다른 JAR 파일에 포함 된 JAR 파일을 포함 하는 Java를 지정할 수 있습니까?

답변:


94

응용 프로그램과 필요한 라이브러리가 포함 된 단일 jar을 만들려고하면 두 가지 방법이 있습니다. 첫 번째는 One-Jar 이며, 특수 클래스 로더를 사용하여 항아리를 중첩 할 수 있습니다. 두 번째는 UberJar (또는 Shade )이며 포함 된 라이브러리를 분해 하고 모든 클래스를 최상위 jar에 넣습니다.

또한 UberJar와 Shade는 각각 Maven1과 Maven2 용 플러그인입니다. 아래에서 언급했듯이 어셈블리 플러그인을 사용할 수도 있습니다 (실제로는 훨씬 강력하지만 올바르게 구성하기가 훨씬 어렵습니다).


81
5 년 후 여기 있습니다. 이것이 여전히 사실 인 것 같습니다. 매우 슬픈 :(
T3rm1

3
내가 현재 알고있는 가장 좋은 방법은 IntelliJ jar 아티팩트를 사용하는 것입니다. 종속 항아리에서 모든 클래스를 추출하여 하나의 항아리에 넣습니다.
enl8enmentnow

2
서명이 필요한 BouncyCastle과 같은 JCE 구현을 사용할 때와 같은 일부 상황에서는 불가능합니다.
debuti

1
@ BrainSlugs83 ... 당신은 무엇을하려고합니까? One-Jar의 클래스 로더와 패키지 프로그램은 여전히 ​​Jar (Java SE 용) 프로젝트에 Jar를 포함시키는 것에 대한 대답이라고 생각합니다. UberJar를 사용하면 클래스 파일을 Jar로 추출하여 문제를 해결할 수 있습니다.
Steve Moyer

1
UberJar 링크에는 로그인 자격 증명이 필요합니다. 후속 웹 페이지가 있습니까?
토머스 웰러

50

이러한 "JAR 컨텐츠 분해"솔루션을 사용하지 않으려 고합니다. 그것들은 확실히 물건을보기 어렵게 만듭니다 (모든 것이 같은 레벨에서 폭발하기 때문에). 또한 이름 충돌이있을 수 있습니다 (사람들이 적절한 패키지를 사용하는 경우에는 발생하지 않아야하지만 항상이를 제어 할 수는 없습니다).

원하는 기능은 상위 25 개의 Sun RFE 중 하나입니다 . RFE 4648386 Sun이 무한한 지혜로 우선 순위가 낮은 것으로 지정한 . 우리는 태양이 깨어나기를 바랄뿐입니다 ...

한편, 내가 찾은 최고의 솔루션 (Sun이 JDK로 복사하기를 원함 )은 사용자 정의 클래스 로더 JarClassLoader 를 사용하는 입니다.


4
이름 충돌은 실제로 log4j 구성 및 라이센스 텍스트와 같은 것들에서 발생할 수 있습니다.
Michael Borgwardt

1
슬프게도 JarClassLoader는 GPLv3 / 상업용이므로 "태양 (현재 oracle)에 의해 복사되지"않을 것이므로 내부 정치적 영향력과 구매할 시간이 없으면 상업적으로 사용할 수 없습니다. 그러나 나는 현재 디렉토리에있는 barf가 나쁜 것임을 동의합니다.
거스

이 답변의 아이디어 +1 (답변 자체를 +1하지는 않지만) : 서명 된 JAR 파일을 다시 패키지 할 수 없으므로이 기술은 많은 상황에서 사용될 수 없습니다 (예 : Java의 activation.jar).
Christopher Schultz

31

몇 가지 연구를 한 후에 maven 또는 타사 확장 프로그램을 필요로하지 않는 방법을 찾았습니다.

매니페스트 파일에서 "클래스 경로"를 사용할 수 있습니다.

예를 들면 다음과 같습니다.

매니페스트 파일 MANIFEST.MF 만들기

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

모든 클래스를 컴파일하고 실행 jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

c아카이브 생성을 f의미하는 것은 파일 v을 자세하게 입력하기위한 것임을 나타냅니다. m 은 사용자 정의 매니페스트 파일을 전달 함을 의미합니다.

jar 패키지에 lib를 포함했는지 확인하십시오. 일반적인 방법으로 jar를 실행할 수 있어야합니다.

기반으로 : http://www.ibm.com/developerworks/library/j-5things6/

클래스 경로에 필요한 다른 모든 정보는 여기에서 찾을 수 있습니다


19
이 답변은 효과가 없습니다 . 오라클 문서에서 (위의 바나나로 링크 됨) : "Class-Path 헤더는 JAR 파일 내의 JAR 파일이 아닌 로컬 네트워크상의 클래스 또는 JAR 파일을 가리 킵니다"
sebnukem

이것이 Android 설정에서도 사용될 수 있는지 여부는 알려져 있습니다.
Mostowski Collapse

2
실행 가능한 jar 시나리오 (테스트)에서 작동하지만 라이브러리 jar에 jar를 포함하려는 경우 작동하지 않을 수 있습니다.
Cychih

5
오, 안돼요, 일단 움직이면 custom_lib.jar항아리를 더 이상 실행할 수 없습니다 :(
Cychih

Class-Path에 여러 개의 jar을 어떻게 지정할 수 있습니까?
Abhishek Tiwari

22

zipgroupfileset 태그를 사용하십시오 ( 파일 세트 태그 와 동일한 속성을 사용함 ). 디렉토리의 모든 파일을 압축 해제하고 새 아카이브 파일에 추가합니다. 추가 정보: http://ant.apache.org/manual/Tasks/zip.html

이것은 jar-in-a-jar 문제를 해결하는 매우 유용한 방법입니다. 무엇을 해야할지 알아 내려고 하면서이 정확한 StackOverflow 질문을 봤기 때문에 알고 있습니다. 항아리 또는 항아리 폴더를 Ant가있는 하나의 빌드 된 항아리에 패키지하려면이 클래스 경로 또는 타사 플러그인을 잊어 버려라.

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

8

개미로 빌드하는 경우 (나는 개미의 개미를 사용하고 있습니다) 개미에게 추가하여 추가 jar 파일을 추가 할 수 있습니다 ... 여러 사람이 프로젝트를 관리하지만 작동하는 경우 반드시 가장 좋은 방법은 아닙니다. 한 사람의 프로젝트를 위해 쉽고 쉽습니다.

예를 들어 .jar 파일을 작성하는 대상은 다음과 같습니다.

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

방금 한 줄을 추가하여 만들었습니다.

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

어디

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

외부 항아리가있는 디렉토리였습니다. 그리고 그게 다야...


6

클래스 로더를 작성하지 않고서는 안됩니다. 항아리를 클래스의 클래스 경로에 추가 할 수 있지만 주 항아리에 포함되지 않은 병치해야합니다.


2

이 작업 또는이를 지원하는 타사 라이브러리를 수행하려면 사용자 정의 클래스 로더를 빌드해야합니다. 가장 좋은 방법은 런타임에서 jar를 추출하여 클래스 경로에 추가하거나 이미 클래스 경로에 추가하는 것입니다.


2

maven assembly plugin 이라는 플러그인이있는 Java 빌드에 maven을 사용합니다. 합니다.

그것은 당신이 요구하는 것을하지만 다른 제안들과 같이 설명합니다-본질적으로 모든 종속 항아리를 폭발시키고 그것들을 단일 항아리로 재조합


메이븐 어셈블리 플러그인 사용에 매우 고통스러운 ... UberJar과 그늘 Maven1 및 Maven2 플러그인입니다 (제가 위에서 언급해야 할 사실은, 그래서 지금 할 것)
스티브 모이어

2

eclpise IDE가있는 경우 JAR을 내보내고 "필요한 라이브러리를 생성 된 JAR로 패키지화"를 선택하면됩니다. eclipse는 필요한 종속 JAR을 생성 된 JAR에 자동으로 추가하고 이러한 JAR을 자동으로로드하는 일부 Eclipse 사용자 정의 클래스 로더를 생성합니다.


1

패키지 시스템이 깔끔하게 분리되어 있어야하기 때문에 모든 파일을 동일한 수준에서 추출한 다음 결과에서 항아리를 만들도록 조언하려고했습니다. 그것은 수동적 인 방법 일 것입니다. 스티브가 표시 한 도구가 훌륭하게 수행 할 것이라고 생각합니다.



1

Eclipse를 사용하는 경우 매우 쉬운 방법이 있습니다.

프로젝트를 "실행 가능"Jar 파일로 내보내십시오 (Eclipse 내에서 프로젝트 폴더를 마우스 오른쪽 단추로 클릭하고 "내보내기 ..."를 선택하십시오). 내보내기 설정을 구성 할 때 "필요한 라이브러리를 생성 된 Jar로 추출"을 선택하십시오. "... 추출"을 선택, 마음에 유지하고 있지"패키지 필수 라이브러리 ..."가 " .

또한 : 내보내기 설정에서 실행 구성을 선택해야합니다. 따라서 어떤 클래스에서는 항상 빈 main ()을 만들어 실행 구성에 사용할 수 있습니다.

어쨌든,이되지 보장 사업에 100 %의 시간을 - 당신은 당신이 당신이 포함하고있는 Jar 파일의 라이센스를 확인하기 위해 알려주는 팝업 메시지가 나타납니다 및 서명 파일을 복사하지에 대해 뭔가 것 같은. 그러나 나는 수년간 이것을 왔으며 결코 문제가 발생하지 않았습니다.


0

Uber-dir로 추출하면 root : \ java를 사용하고 버전이있는 패키지에 콘센트 코드가 있어야하므로 나에게 효과적입니다. 즉 ca.tecreations-1.0.0. 항아리는 다운로드 한 위치에서 그대로 유지되므로 서명해도됩니다. 타사 서명은 그대로, c : \ java로 추출하십시오. 내 프로젝트 디렉토리가 있습니다. 실행기에서 실행하므로 java -cp c : \ java 실행기


c : \ java \ jars의 항아리. c : \ java의 소스, 바이너리 및 리소스 백업, 속성, keystore_private를 제외하십시오. c : \ java로 압축을 풀고 클래스 경로 형성 도구로 실행하십시오. 따라서 ca.tecreations.system.tools.SystemTool 또는 비슷한 Java 클래스 일 수 있습니다. 그것을 실행하십시오.
Tim de Vries
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.