런타임에 JAR 파일을 동적으로로드하는 방법은 무엇입니까?


308

Java에서 왜 이렇게하기가 어렵습니까? 모든 종류의 모듈 시스템을 원한다면 JAR 파일을 동적으로로드 할 수 있어야합니다. 나는 당신 자신의 ClassLoader것을 작성하여 그것을 수행하는 방법이 있다고 들었지만, 그것은 적어도 내 생각으로는 JAR 파일을 가진 메소드를 인수로 호출하는 것만 큼 쉬워야 할 일이 많이 있습니다.

이를 수행하는 간단한 코드에 대한 제안 사항이 있습니까?


4
동일한 작업을 수행하고 싶지만 더 안전한 샌드 박스 환경에서로드 된 jar를 실행하십시오 (확실히 보안상의 이유로). 예를 들어 모든 네트워크 및 파일 시스템 액세스를 차단하고 싶습니다.
Jus12

답변:


253

어려운 이유는 보안입니다. 클래스 로더는 변경 불가능합니다. 런타임에 클래스를 고의로 추가 할 수 없어야합니다. 실제로 시스템 클래스 로더와 함께 작동하는 것에 매우 놀랐습니다. 자식 클래스 로더를 만드는 방법은 다음과 같습니다.

URLClassLoader child = new URLClassLoader(
        new URL[] {myJar.toURI().toURL()},
        this.getClass().getClassLoader()
);
Class classToLoad = Class.forName("com.MyClass", true, child);
Method method = classToLoad.getDeclaredMethod("myMethod");
Object instance = classToLoad.newInstance();
Object result = method.invoke(instance);

고통 스럽지만 거기에 있습니다.


16
이 접근법의 유일한 문제점은 어떤 클래스에 어떤 클래스가 있는지 알아야한다는 것입니다. jar 디렉토리를로드 한 다음 클래스를 인스턴스화하는 것과 반대로. 나는 그것을 오해하고 있습니까?
Allain Lalonde

10
이 메소드는 IDE에서 실행될 때 훌륭하게 작동하지만 JAR을 빌드하면 Class.forName ()을 호출 할 때 ClassNotFoundException이 발생합니다.
darrickc

29
이 방법을 사용하면 각 클래스에 대해이로드 메소드를 두 번 이상 호출하지 않아야합니다. 모든로드 작업에 대해 새 클래스 로더를 작성하므로 클래스가 이미로드되었는지 여부를 알 수 없습니다. 이것은 나쁜 결과를 초래할 수 있습니다. 예를 들어 클래스가 여러 번로드되어 정적 필드가 여러 번 존재하므로 싱글 톤이 작동하지 않습니다.
Eduard Wirch

8
공장. 항아리 안의 다른 클래스에 대한 의존성조차도. 첫 번째 줄은 불완전했습니다. 내가 사용하는 URLClassLoader child = new URLClassLoader (new URL[] {new URL("file://./my.jar")}, Main.class.getClassLoader());jar 파일이 호출 될 것을 가정 my.jar하고 같은 디렉토리에 있습니다.

4
url = file.toURI (). toURL ();을 잊지 마십시오.
johnstosh

139

다음 솔루션은 리플렉션을 사용하여 캡슐화를 우회하기 때문에 해킹 적이지만 완벽하게 작동합니다.

File file = ...
URL url = file.toURI().toURL();

URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, url);

40
이 응답에 대한 모든 활동은 다른 시스템의 프로덕션에서 얼마나 많은 핵을 실행하고 있는지 궁금합니다. 나는 답을 알고 싶지 않다
Andrei Savu

6
시스템 클래스 로더가 URLClassLoader가 아닌 다른 것이라면 잘 작동하지 않습니다 ...
Gus

6
Java 9+는 URLClassLoader.class.getDeclaredMethod("addURL", URL.class)불법적 인 리플렉션 사용이며 향후 실패 할 것이라고 경고합니다 .
Charlweed

1
Java 9 이상에서 작동하도록이 코드를 업데이트하는 방법에 대한 아이디어가 있습니까?
FiReTiTi

1
@FiReTiTi !!
Mordechai

51

예를 들어 Eclipse 플랫폼 에서 구현 된 OSGi를 살펴보아야 합니다. 정확히 그렇습니다. 효과적으로 JAR 파일 인 소위 번들을 설치, 설치 제거, 시작 및 중지 할 수 있습니다. 그러나 런타임시 JAR 파일에서 동적으로 발견 될 수있는 서비스와 같은 서비스를 제공하므로 약간 더 많은 작업을 수행합니다.

또는 Java 모듈 시스템 의 사양을 참조하십시오 .


41

방법에 대한 JCL 클래스 로더 프레임 워크 ? 나는 그것을 사용하지 않았 음을 인정해야하지만 유망 해 보인다.

사용 예 :

JarClassLoader jcl = new JarClassLoader();
jcl.add("myjar.jar"); // Load jar file  
jcl.add(new URL("http://myserver.com/myjar.jar")); // Load jar from a URL
jcl.add(new FileInputStream("myotherjar.jar")); // Load jar file from stream
jcl.add("myclassfolder/"); // Load class folder  
jcl.add("myjarlib/"); // Recursively load all jar files in the folder/sub-folder(s)

JclObjectFactory factory = JclObjectFactory.getInstance();
// Create object of loaded class  
Object obj = factory.create(jcl, "mypackage.MyClass");

9
또한 버그가 있고 findResources (...)와 같은 중요한 구현이 누락되었습니다. ) = 어떤 일이 작동하지 않는 이유를 조사하고 멋진 밤을 보낼 준비를
세르게이 Karpushin

프로젝트가 시간이 지남에 따라 두 번째 주요 버전으로 업데이트 된 이후 @ SergeyKarpushin의 주장이 여전히 존재하는지 궁금합니다. 경험을 듣고 싶습니다.
Erdin Eray 2019

2
@ ErdinEray, 우리가 OpenJDK로 전환하도록 "강제"된 이후 나 자신에게 묻는 것도 좋은 질문입니다. 나는 여전히 Java 프로젝트에서 일하고 있으며, Open JDK가 요즘 실패한다는 증거는 없습니다 (이전에는 문제가있었습니다). 다른 것에 부딪 칠 때까지 청구를 철회 한 것 같습니다.
Sergey Karpushin '12

20

더 이상 사용되지 않는 버전이 있습니다. 더 이상 사용되지 않는 기능을 제거하기 위해 원본을 수정했습니다.

/**************************************************************************************************
 * Copyright (c) 2004, Federal University of So Carlos                                           *
 *                                                                                                *
 * All rights reserved.                                                                           *
 *                                                                                                *
 * Redistribution and use in source and binary forms, with or without modification, are permitted *
 * provided that the following conditions are met:                                                *
 *                                                                                                *
 *     * Redistributions of source code must retain the above copyright notice, this list of      *
 *       conditions and the following disclaimer.                                                 *
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of   *
 *     * conditions and the following disclaimer in the documentation and/or other materials      *
 *     * provided with the distribution.                                                          *
 *     * Neither the name of the Federal University of So Carlos nor the names of its            *
 *     * contributors may be used to endorse or promote products derived from this software       *
 *     * without specific prior written permission.                                               *
 *                                                                                                *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS                            *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT                              *
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR                          *
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR                  *
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,                          *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,                            *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR                             *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF                         *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING                           *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS                             *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                   *
 **************************************************************************************************/
/*
 * Created on Oct 6, 2004
 */
package tools;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * Useful class for dynamically changing the classpath, adding classes during runtime. 
 */
public class ClasspathHacker {
    /**
     * Parameters of the method to add an URL to the System classes. 
     */
    private static final Class<?>[] parameters = new Class[]{URL.class};

    /**
     * Adds a file to the classpath.
     * @param s a String pointing to the file
     * @throws IOException
     */
    public static void addFile(String s) throws IOException {
        File f = new File(s);
        addFile(f);
    }

    /**
     * Adds a file to the classpath
     * @param f the file to be added
     * @throws IOException
     */
    public static void addFile(File f) throws IOException {
        addURL(f.toURI().toURL());
    }

    /**
     * Adds the content pointed by the URL to the classpath.
     * @param u the URL pointing to the content to be added
     * @throws IOException
     */
    public static void addURL(URL u) throws IOException {
        URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
        Class<?> sysclass = URLClassLoader.class;
        try {
            Method method = sysclass.getDeclaredMethod("addURL",parameters);
            method.setAccessible(true);
            method.invoke(sysloader,new Object[]{ u }); 
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IOException("Error, could not add URL to system classloader");
        }        
    }

    public static void main(String args[]) throws IOException, SecurityException, ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{
        addFile("C:\\dynamicloading.jar");
        Constructor<?> cs = ClassLoader.getSystemClassLoader().loadClass("test.DymamicLoadingTest").getConstructor(String.class);
        DymamicLoadingTest instance = (DymamicLoadingTest)cs.newInstance();
        instance.test();
    }
}

19
나는 오래된 스레드를 범하는 것을 싫어하지만 stackoverflow의 모든 내용은 CC 라이센스가 있음을 지적하고 싶습니다. 귀하의 저작권 정보는 사실상 효력이 없습니다. stackoverflow.com/faq#editing
Huckle

43
음 기술적으로 원본 컨텐츠는 CC 라이센스가 있지만 여기에 저작권이있는 컨텐츠를 게시하더라도 컨텐츠가 저작권이 있다는 사실을 제거하지는 않습니다. Mickey Mouse의 사진을 게시해도 CC 라이센스가 없습니다. 그래서 나는 저작권 진술을 다시 추가하고 있습니다.
Jason S

19

여기에 나열된 대부분의 솔루션은 구성하기 어려운 에이전트 (JDK 9 이전)이거나 더 이상 작동하지 않습니다 (JDK 9 이후) . 명확하게 문서화 된 방법을 언급하지 않은 사람은 정말 충격적입니다 .

커스텀 시스템 클래스 로더를 만들면 원하는대로 자유롭게 할 수 있습니다. 반영이 필요하지 않으며 모든 클래스가 동일한 클래스 로더를 공유합니다.

JVM을 시작할 때이 플래그를 추가하십시오.

java -Djava.system.class.loader=com.example.MyCustomClassLoader

클래스 로더에는 클래스 로더를 허용하는 생성자가 있어야하며, 클래스 로더를 상위로 설정해야합니다. JVM 시작시 생성자가 호출되고 실제 시스템 클래스 로더가 전달되고 기본 클래스는 사용자 정의 로더에 의해로드됩니다.

항아리를 추가하려면 전화 ClassLoader.getSystemClassLoader()하여 수업에 캐스트하십시오.

신중하게 제작 된 클래스 로더에 대해서는 이 구현 을 확인하십시오 . add()방법을 공개로 변경할 수 있습니다 .


감사합니다-정말 도움이됩니다! JDK 8 이전 버전의 웹 사용 방법에 대한 다른 모든 참조에는 여러 가지 문제가 있습니다.
Vishal Biyani

15

함께 자바 9 과 답변 URLClassLoader현재 오류가 같이 제공 :

java.lang.ClassCastException: java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClassLoader

사용 된 클래스 로더가 변경 되었기 때문입니다. 대신 시스템 클래스 로더에 추가하기 위해 에이전트를 통해 인스 트루먼 테이션 API를 사용할 수 있습니다 .

에이전트 클래스를 작성하십시오.

package ClassPathAgent;

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;

public class ClassPathAgent {
    public static void agentmain(String args, Instrumentation instrumentation) throws IOException {
        instrumentation.appendToSystemClassLoaderSearch(new JarFile(args));
    }
}

META-INF / MANIFEST.MF를 추가하고 에이전트 클래스가있는 JAR 파일에 넣으십시오.

Manifest-Version: 1.0
Agent-Class: ClassPathAgent.ClassPathAgent

에이전트를 실행하십시오.

이것은 사용 바이트 친구 에이전트 실행중인 JVM에 에이전트를 추가 할 라이브러리를 :

import java.io.File;

import net.bytebuddy.agent.ByteBuddyAgent;

public class ClassPathUtil {
    private static File AGENT_JAR = new File("/path/to/agent.jar");

    public static void addJarToClassPath(File jarFile) {
        ByteBuddyAgent.attach(AGENT_JAR, String.valueOf(ProcessHandle.current().pid()), jarFile.getPath());
    }
}

9

내가 찾은 가장 좋은 것은 XBean 프로젝트의 일부인 org.apache.xbean.classloader.JarFileClassLoader 입니다 .

다음은 특정 디렉토리의 모든 lib 파일에서 클래스 로더를 작성하기 위해 과거에 사용한 짧은 방법입니다.

public void initialize(String libDir) throws Exception {
    File dependencyDirectory = new File(libDir);
    File[] files = dependencyDirectory.listFiles();
    ArrayList<URL> urls = new ArrayList<URL>();
    for (int i = 0; i < files.length; i++) {
        if (files[i].getName().endsWith(".jar")) {
        urls.add(files[i].toURL());
        //urls.add(files[i].toURI().toURL());
        }
    }
    classLoader = new JarFileClassLoader("Scheduler CL" + System.currentTimeMillis(), 
        urls.toArray(new URL[urls.size()]), 
        GFClassLoader.class.getClassLoader());
}

그런 다음 클래스 로더를 사용하려면 다음을 수행하십시오.

classLoader.loadClass(name);

프로젝트가 잘 관리되지 않은 것 같습니다. 예를 들어 미래의 로드맵에는 2014 년에 대한 여러 릴리스가 포함되어 있습니다.
Zero3

6

Android에서 작업중인 경우 다음 코드가 작동합니다.

String jarFile = "path/to/jarfile.jar";
DexClassLoader classLoader = new DexClassLoader(jarFile, "/data/data/" + context.getPackageName() + "/", null, getClass().getClassLoader());
Class<?> myClass = classLoader.loadClass("MyClass");

6

최신 버전의 Java와 호환되는 Allain의 방법에 대한 빠른 해결 방법은 다음과 같습니다.

ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
    Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);
    method.invoke(classLoader, new File(jarPath).toURI().toURL());
} catch (NoSuchMethodException e) {
    Method method = classLoader.getClass()
            .getDeclaredMethod("appendToClassPathForInstrumentation", String.class);
    method.setAccessible(true);
    method.invoke(classLoader, jarPath);
}

특정 JVM의 내부 구현에 대한 지식에 의존하므로 이상적이지 않으며 보편적 인 솔루션이 아닙니다. 그러나 표준 OpenJDK 또는 Oracle JVM을 사용한다는 것을 알고 있다면 빠르고 쉬운 해결 방법입니다. 새 JVM 버전이 출시 될 때 어느 시점에서 중단 될 수도 있으므로이를 명심해야합니다.


자바 11.0.2로, 내가 얻을 :Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make void jdk.internal.loader.ClassLoaders$AppClassLoader.appendToClassPathForInstrumentation(java.lang.String) accessible: module java.base does not "opens jdk.internal.loader" to unnamed module @18ef96
리처드 잭

애플리케이션 서버 환경에서 Java 8 EE와 함께 작동합니다.
Jan

4

jodonnell이 제안한 솔루션은 훌륭하지만 약간 향상되어야합니다. 이 게시물을 사용하여 응용 프로그램을 성공적으로 개발했습니다.

현재 스레드 할당

먼저 우리는 추가해야합니다

Thread.currentThread().setContextClassLoader(classLoader);

또는 jar에 저장된 자원 (예 : spring / context.xml)을로드 할 수 없습니다.

포함하지 마십시오

항아리를 부모 클래스 로더에 넣거나 누가 무엇을로드하는지 이해할 수 없습니다.

URLClassLoader를 사용하여 jar를 다시로드 할 때의 문제점 도 참조하십시오.

그러나 OSGi 프레임 워크가 가장 좋은 방법입니다.


2
귀하의 답변은 약간 혼란스러워 보이며 아마도 단순한 개선 일 경우 jodonnell의 답변에 대한 의견으로 더 적합 할 것입니다.
Zero3

4

Allain의 해킹 솔루션의 다른 버전으로 JDK 11에서도 작동합니다.

File file = ...
URL url = file.toURI().toURL();
URLClassLoader sysLoader = new URLClassLoader(new URL[0]);

Method sysMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
sysMethod.setAccessible(true);
sysMethod.invoke(sysLoader, new Object[]{url});

JDK 11에서는 사용 중단 경고가 표시되지만 JDK 11에서 Allain 솔루션을 사용하는 사람들은 임시 솔루션으로 사용됩니다.


항아리도 제거 할 수 있습니까?
user7294900

3

나를 위해 작동하는 인스 트루먼 테이션을 사용하는 또 다른 작업 솔루션. 종속 클래스의 클래스 가시성에 대한 문제점을 피하면서 클래스 로더 검색을 수정하는 이점이 있습니다.

에이전트 클래스 만들기

이 예제에서는 명령 행에서 호출 한 동일한 jar에 있어야합니다.

package agent;

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;

public class Agent {
   public static Instrumentation instrumentation;

   public static void premain(String args, Instrumentation instrumentation) {
      Agent.instrumentation = instrumentation;
   }

   public static void agentmain(String args, Instrumentation instrumentation) {
      Agent.instrumentation = instrumentation;
   }

   public static void appendJarFile(JarFile file) throws IOException {
      if (instrumentation != null) {
         instrumentation.appendToSystemClassLoaderSearch(file);
      }
   }
}

MANIFEST.MF 수정

에이전트에 대한 참조 추가 :

Launcher-Agent-Class: agent.Agent
Agent-Class: agent.Agent
Premain-Class: agent.Agent

실제로 Netbeans를 사용하므로이 게시물 은 manifest.mf를 변경하는 방법에 도움 됩니다.

달리는

Launcher-Agent-Class에이전트는 JDK 9+에서만 지원되며 명령 행에서 에이전트를 명시 적으로 정의하지 않고 에이전트를로드해야합니다.

 java -jar <your jar>

JDK 6+에서 작동하는 방식은 -javaagent인수를 정의하는 것입니다 .

java -javaagent:<your jar> -jar <your jar>

런타임에 새로운 Jar 추가

그런 다음 다음 명령을 사용하여 필요에 따라 jar을 추가 할 수 있습니다.

Agent.appendJarFile(new JarFile(<your file>));

설명서에서 이것을 사용하는 데 아무런 문제가 없었습니다.


이 솔루션을 사용할 때 어떤 이유로 "스레드"main "java.lang.ClassNotFoundException : agent.Agent"에 예외가 발생합니다. 나는 그래서 나는 확실히 그것을 거기, 내 주요 "전쟁"응용 프로그램에 "에이전트"클래스를 패키지
세르게이 Ledvanov

3

미래에 누군가가 이것을 검색하는 경우이 방법은 OpenJDK 13.0.2에서 작동합니다.

런타임에 동적으로 인스턴스화 해야하는 많은 클래스가 있으며 각각 잠재적으로 다른 클래스 경로가 있습니다.

이 코드에는 이미로드하려는 클래스에 대한 일부 메타 데이터를 보유하는 pack이라는 객체가 있습니다. getObjectFile () 메소드는 클래스의 클래스 파일 위치를 리턴합니다. getObjectRootPath () 메소드는 인스턴스화하려는 클래스를 포함하는 클래스 파일을 포함하는 bin / 디렉토리의 경로를 리턴합니다. getLibPath () 메소드는 클래스가 속한 모듈의 클래스 경로를 구성하는 jar 파일을 포함하는 디렉토리에 대한 경로를 리턴합니다.

File object = new File(pack.getObjectFile()).getAbsoluteFile();
Object packObject;
try {
    URLClassLoader classloader;

    List<URL> classpath = new ArrayList<>();
    classpath.add(new File(pack.getObjectRootPath()).toURI().toURL());
    for (File jar : FileUtils.listFiles(new File(pack.getLibPath()), new String[] {"jar"}, true)) {
        classpath.add(jar.toURI().toURL());
    }
    classloader = new URLClassLoader(classpath.toArray(new URL[] {}));

    Class<?> clazz = classloader.loadClass(object.getName());
    packObject = clazz.getDeclaredConstructor().newInstance();

} catch (Exception e) {
    e.printStackTrace();
    throw e;
}
return packObject;

나는 이것을하기 위해 Maven 의존성 : org.xeustechnologies : jcl-core : 2.8을 사용하고 있었지만 JDK 1.8을 지나간 후에 때때로 멈추고 Reference :: waitForReferencePendingList ()에서 "참조 대기 중"으로 멈추지 않았다.

또한 인스턴스화하려는 클래스가 이미 인스턴스화 한 클래스와 동일한 모듈에있는 경우 재사용 할 수 있도록 클래스 로더 맵을 유지하고 있습니다.


2

내가 시작한이 프로젝트를 살펴보십시오 : proxy-object lib

이 lib는 파일 시스템이나 다른 위치에서 jar 파일을로드합니다. jar가 라이브러리 충돌이 없는지 확인하기 위해 클래스 로더를 전용으로 사용합니다. 사용자는로드 된 jar에서 오브젝트를 작성하고 그에 대한 메소드를 호출 할 수 있습니다. 이 lib는 Java 7을 지원하는 코드베이스에서 Java 8로 컴파일 된 jar을로드하도록 설계되었습니다.

객체를 만들려면

    File libDir = new File("path/to/jar");

    ProxyCallerInterface caller = ObjectBuilder.builder()
            .setClassName("net.proxy.lib.test.LibClass")
            .setArtifact(DirArtifact.builder()
                    .withClazz(ObjectBuilderTest.class)
                    .withVersionInfo(newVersionInfo(libDir))
                    .build())
            .build();
    String version = caller.call("getLibVersion").asString();

ObjectBuilder는 팩토리 메소드, 정적 함수 호출 및 인터페이스 구현 콜백을 지원합니다. readme 페이지에 더 많은 예제를 게시 할 것입니다.


2

이것은 늦은 응답 일 수 있습니다 .DataMelt ( http://jwork.org/dmelt )의 jhplot.Web 클래스를 사용 하여이 작업을 수행 할 수 있습니다 (fastutil-8.2.2.jar의 간단한 예 ).

import jhplot.Web;
Web.load("http://central.maven.org/maven2/it/unimi/dsi/fastutil/8.2.2/fastutil-8.2.2.jar"); // now you can start using this library

문서에 따르면이 파일은 "lib / user"에 다운로드 된 후 동적으로로드되므로 동일한 프로그램에서이 jar 파일의 클래스를 사용하여 즉시 시작할 수 있습니다.


1

java 8 및 java 9 이상 모두에 대해 런타임에 jar 파일을로드해야했습니다 (위의 주석은이 두 버전 모두에서 작동하지 않습니다). 이를 수행하는 방법은 다음과 같습니다 (Spring Boot 1.5.2를 사용하는 경우).

public static synchronized void loadLibrary(java.io.File jar) {
    try {            
        java.net.URL url = jar.toURI().toURL();
        java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
        method.setAccessible(true); /*promote the method to public access*/
        method.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{url});
    } catch (Exception ex) {
        throw new RuntimeException("Cannot load library from jar file '" + jar.getAbsolutePath() + "'. Reason: " + ex.getMessage());
    }
}

-2

개인적으로 java.util.ServiceLoader 가 작업을 잘 수행 한다는 것을 알았 습니다. 여기 에서 예를 얻을 수 있습니다 .


11
ServiceLoader는 런타임에 jar 파일을 동적으로 추가하지 않습니다. jar 파일은 이전에 클래스 경로에 있어야합니다.
angelcervera
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.