JAR dosyalarını Çalışma zamanında dinamik olarak nasıl yükleyebilirim?


308

Java ile bunu yapmak neden bu kadar zor? Herhangi bir modül sistemine sahip olmak istiyorsanız, JAR dosyalarını dinamik olarak yükleyebilmeniz gerekir. Bana kendi yazarak bunu yapmanın bir yolu var ClassLoader, ama bu (en azından aklımda) bir argüman olarak bir JAR dosyası ile bir yöntem çağırmak kadar kolay bir şey için çok iş.

Bunu yapan basit kod için herhangi bir öneriniz var mı?


4
Aynı şeyi yapmak istiyorum ama yüklü kavanozu daha korumalı bir ortamda (güvenlik nedeniyle açıkçası) çalıştırmak istiyorum. Örneğin, tüm ağ ve dosya sistemi erişimini engellemek istiyorum.
Jus12

Yanıtlar:


253

Zor olmasının nedeni güvenlik. Sınıf yükleyicilerin değişmez olması amaçlanmıştır; çalışma zamanında buna willy-nilly ekleyemezsiniz. Aslında sistem sınıf yükleyicisi ile çalışan çok şaşırdım. Kendi alt sınıf yükleyicinizi nasıl yapacağınız aşağıda açıklanmıştır:

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

Acı verici, ama işte burada.


16
Bu yaklaşımla ilgili tek sorun, hangi kavanozlarda hangi sınıfların olduğunu bilmeniz gerektiğidir. Sadece bir kavanoz dizini yüklemek ve daha sonra sınıfları başlatmak yerine. Yanlış anlıyor muyum?
Allain Lalonde

10
Bu yöntem IDE içinde çalışırken harika çalışıyor, ancak JAR'ımı oluşturduğumda Class.forName () çağırırken bir ClassNotFoundException alıyorum.
darrickc

29
Bu yaklaşımı kullanarak, bu yükleme yöntemini her sınıf için birden fazla çağırmayacağınızdan emin olmanız gerekir. Her yükleme işlemi için yeni bir sınıf yükleyici oluşturduğunuzdan, sınıfın önceden yüklenmiş olup olmadığını bilemez. Bunun kötü sonuçları olabilir. Örneğin, sınıf birkaç kez yüklendiği ve böylece statik alanlar birkaç kez var olduğu için singletonlar çalışmıyor.
Eduard Wirch

8
İşler. Kavanozun içindeki diğer sınıflara bağımlılıklarda bile. İlk satır eksikti. URLClassLoader child = new URLClassLoader (new URL[] {new URL("file://./my.jar")}, Main.class.getClassLoader());Jar dosyasının çağrıldığını my.jarve aynı dizinde bulunduğunu varsayarak kullandım .
çene

4
URL url = file.toURI (). ToURL ();
johnstosh

139

Aşağıdaki çözüm, kapsüllemeyi atlamak için yansıma kullandığından, haksızdır, ancak kusursuz çalışır:

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
Bu yanıttaki tüm etkinlik, farklı sistemlerde üretimde ne kadar hack yaptığımızı merak etmemi sağlıyor. Cevabı bilmek istediğimden emin değilim
Andrei Savu

6
Sistem sınıfı yükleyici bir URLClassLoader dışında bir şey olursa çok iyi çalışmaz ...
Gus

6
Java 9+, URLClassLoader.class.getDeclaredMethod("addURL", URL.class)yasadışı bir yansıma kullanımı olduğu konusunda uyarır ve gelecekte başarısız olur.
Charlweed

1
Java 9+ ile çalışmak için bu kodu nasıl güncelleyeceğiniz hakkında bir fikriniz var mı?
FiReTiTi

1
@FiReTiTi Evet !!
Mordechai

51

Eclipse Platformunda uygulanan OSGi'ye bir göz atmalısınız . Tam olarak bunu yapıyor. Etkin bir şekilde JAR dosyaları olan demetleri yükleyebilir, kaldırabilir, başlatabilir ve durdurabilirsiniz. Ancak, çalışma zamanında JAR dosyalarında dinamik olarak keşfedilebilen hizmetler sunduğu için biraz daha fazlasını yapar.

Veya Java Modül Sistemi teknik özelliklerine bakın .


41

Nasıl hakkında JCL sınıf yükleyici çerçeve ? İtiraf etmeliyim, kullanmadım, ama umut verici görünüyor.

Kullanım örneği:

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
Ayrıca buggy ve bazı önemli uygulamaları eksik yani findResources (...). Bazı şeylerin neden işe yaramadığını araştırmak için harika geceler geçirmeye hazır olun =)
Sergey Karpushin

Merak ediyorum @ SergeyKarpushin'in iddiaları hala proje ikinci büyük sürüme güncellendiğinden beri var. Deneyimi duymak istiyorum.
Erdin Eray

2
@ErdinEray, OpenJDK'ya geçmek zorunda kaldığımız için kendime de sormam çok iyi bir soru. Hala java projelerinde çalışıyorum ve Open JDK'nın bu günlerde başarısız olacağına dair hiçbir kanıtım yok (yine de sorunum vardı). Sanırım başka bir şeye çarpana kadar iddiamı geri çekiyorum.
Sergey Karpushin

20

İşte kullanımdan kaldırılmamış bir sürüm. Kullanımdan kaldırılmış işlevselliği kaldırmak için orijinali değiştirdim.

/**************************************************************************************************
 * 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
Eski bir iş parçacığını çarpmaktan nefret ediyorum, ancak stackoverflow'daki tüm içeriğin CC lisanslı olduğunu belirtmek isterim. Telif hakkı bildiriminiz etkili bir şekilde etkisizdir. stackoverflow.com/faq#editing
Huckle

43
Um. Teknik olarak, orijinal içerik CC lisanslıdır, ancak burada telif hakkıyla korunan içerik yayınlarsanız, içeriğin telif hakkıyla korunmuş olduğu gerçeği kaldırılmaz. Mickey Mouse'un bir resmini gönderirsem CC lisanslı yapmaz. Bu yüzden telif hakkı ifadesini tekrar ekliyorum.
Jason S

19

Burada listelenen çözümlerin çoğu ya kesmek (JDK 9 öncesi) yapılandırması zor (ajanlar) ya da artık çalışmıyorsa (JDK 9 sonrası) Kimsenin açıkça belgelenmiş bir yöntemden bahsetmediğini gerçekten şok edici buluyorum .

Özel bir sistem sınıfı yükleyici oluşturabilir ve istediğiniz her şeyi yapabilirsiniz. Yansıtma gerekmez ve tüm sınıflar aynı sınıf yükleyiciyi paylaşır.

JVM'yi başlatırken bu bayrağı ekleyin:

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

Sınıf yükleyicinin, üst öğesi olarak ayarlanması gereken bir sınıf yükleyiciyi kabul eden bir kurucuya sahip olması gerekir. Yapıcı JVM başlangıcında çağrılır ve gerçek sistem sınıf yükleyicisi geçirilir, ana sınıf özel yükleyici tarafından yüklenir.

Kavanoz eklemek için ClassLoader.getSystemClassLoader()onu arayın ve sınıfınıza yayınlayın.

Dikkatle hazırlanmış bir sınıf yükleyici için bu uygulamaya göz atın . Lütfen dikkat,add() yöntemi herkese açık olarak .


Teşekkür ederim - bu gerçekten yararlı! Web'deki diğer tüm referanslar, birden fazla sorunu olan JDK 8 veya öncesi için yöntemleri kullanır.
Vishal Biyani

15

İle Java 9 ile cevaplar URLClassLoaderartık bir hata gibi vermek:

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

Bunun nedeni, kullanılan sınıf yükleyicilerin değişmiş olmasıdır. Bunun yerine, sistem sınıfı yükleyiciye eklemek için Enstrümantasyon'u kullanabilirsiniz. bir aracı aracılığıyla API'sını .

Bir aracı sınıfı oluşturun:

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 ekleyin ve aracı sınıfı ile bir JAR dosyasına koyun:

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

Aracıyı çalıştırın:

Bu , aracıyı çalışan JVM'ye eklemek için byte-buddy-agent kitaplığını kullanır :

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

Bulduğum en iyi şey XBean projesinin bir parçası olan org.apache.xbean.classloader.JarFileClassLoader .

İşte belirli bir dizindeki tüm lib dosyalarından bir sınıf yükleyici oluşturmak için geçmişte kullandığım kısa bir yöntem

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());
}

Ardından sınıf yükleyiciyi kullanmak için şunları yapın:

classLoader.loadClass(name);

Projenin bakımlı olmadığı görülüyor. Gelecek için yol haritaları, örneğin 2014 için birkaç sürüm içeriyor.
Zero3

6

Android'de çalışıyorsanız, aşağıdaki kod çalışır:

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

6

Allain'in yönteminin daha yeni Java sürümleriyle uyumlu hale getirilmesi için hızlı bir çözüm:

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);
}

Belirli JVM'nin dahili uygulaması bilgisine dayandığına dikkat edin, bu yüzden ideal değildir ve evrensel bir çözüm değildir. Ancak standart OpenJDK veya Oracle JVM kullanacağınızı biliyorsanız hızlı ve kolay bir çözümdür. Yeni JVM sürümü yayınlandığında gelecekte bir noktada kırılabilir, bu yüzden bunu aklınızda bulundurmanız gerekir.


Java 11.0.2 ile şunu alıyorum: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
Richard 27ak

Uygulama sunucusu ortamında Java 8 EE ile çalışır.
Ocak

4

Jodonnell tarafından önerilen çözüm iyidir, ancak biraz geliştirilmelidir. Bu yazıyı başvurumu başarıyla geliştirmek için kullandım.

Geçerli iş parçacığını ata

Öncelikle eklemek zorundayız

Thread.currentThread().setContextClassLoader(classLoader);

veya kavanoza depolanan kaynağı (spring / context.xml gibi) yükleyemezsiniz.

Dahil etmeyin

kavanozlarınızı üst sınıf yükleyiciye koyun yoksa kimin neyi yüklediğini anlayamazsınız.

ayrıca bkz. URLClassLoader kullanarak bir kavanozu yeniden yükleme sorunu

Bununla birlikte, OSGi çerçevesi en iyi yol olmaya devam etmektedir.


2
Cevabınız biraz kafa karıştırıcı görünüyor ve belki de sadece basit bir gelişme ise jodonnell'in cevabına bir yorum olarak daha uygun.
Zero3

4

Allain'in hackish çözümünün JDK 11'de de çalışan başka bir sürümü:

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'de bazı kullanımdan çıkarma uyarıları verir, ancak JDK 11'de Allain çözümünü kullananlara geçici bir çözüm olarak hizmet eder.


Kavanozu da çıkarabilir miyim?
kullanıcı7294900

3

Benim için çalışan Enstrümantasyon kullanan başka bir çalışma çözümü. Bağımlı sınıflar için sınıf görünürlüğü sorunlarından kaçınarak sınıf yükleyici aramasını değiştirme avantajına sahiptir:

Bir Ajan Sınıfı oluşturun

Bu örnek için, komut satırı tarafından çağrılan aynı kavanozda olması gerekir:

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 dosyasını değiştirin.

Temsilciye referans ekleme:

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

Aslında Netbeans kullanıyorum, bu yazı manifest.mf nasıl değiştirilir

Koşu

The Launcher-Agent-Classyalnızca JDK 9+ üzerinde desteklenir ve aracıyı komut satırında açıkça tanımlamaksızın yüklemekten sorumludur:

 java -jar <your jar>

JDK 6+ üzerinde çalışma şekli şu -javaagentargümanı tanımlamaktır :

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

Çalışma zamanında yeni kavanoz ekleme

Daha sonra aşağıdaki komutu kullanarak gerektiği şekilde jar ekleyebilirsiniz:

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

Bunu dokümantasyonda kullanırken herhangi bir sorun bulamadım.


Nedense bu çözümü kullanırken "thread in Exception" ana "java.lang.ClassNotFoundException: agent.Agent". "Ajan" sınıfını ana "savaş" uygulamamda
paketledim

3

Gelecekte birisinin bunu araması durumunda, OpenJDK 13.0.2 ile bu şekilde benim için çalışır.

Her biri potansiyel olarak farklı bir sınıfyoluyla, çalışma zamanında dinamik olarak başlatmam gereken birçok sınıfım var.

Bu kodda, yüklemeye çalıştığım sınıf hakkında bazı meta verileri tutan pack adlı bir nesnem zaten var. GetObjectFile () yöntemi, sınıf için sınıf dosyasının konumunu döndürür. GetObjectRootPath () yöntemi, örneklemeye çalıştığım sınıfı içeren sınıf dosyalarını içeren bin / dizinin yolunu döndürür. GetLibPath () yöntemi, sınıfın bir parçası olduğu modülün sınıfyolunu oluşturan jar dosyalarını içeren bir dizinin yolunu döndürür.

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 bağımlılığını kullanıyordum: org.xeustechnologies: jcl-core: 2.8 Bunu daha önce yapmak için, ancak JDK 1.8'i geçtikten sonra bazen dondu ve hiçbir zaman Reference :: waitForReferencePendingList () 'de "referansları beklemede" kaldım.

Ayrıca örnek yükleyicilerin bir haritasını tutuyorum, böylece örneklemeye çalıştığım sınıf zaten başlattığım bir sınıfla aynı modüldeyse, yeniden tavsiye ederim.


2

lütfen başlattığım bu projeye bir göz atın: proxy-object lib

Bu lib jar dosyasını dosya sisteminden veya başka bir konumdan yükleyecektir. Herhangi bir kütüphane çatışması olmadığından emin olmak için kavanoz için bir sınıf yükleyici atayacaktır. Kullanıcılar yüklenen kavanozdan herhangi bir nesne oluşturabilir ve üzerindeki herhangi bir yöntemi çağırabilir. Bu lib, Java 8'de derlenen kavanozları Java 7'yi destekleyen kod tabanından yüklemek için tasarlanmıştır.

Bir nesne oluşturmak için:

    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 fabrika yöntemlerini, statik işlevleri çağırmayı ve geri arama arabirimi uygulamalarını destekler. benioku sayfasında daha fazla örnek yayınlayacağım.


2

Bu geç bir yanıt olabilir, bunu DataMelt ( http://jwork.org/dmelt ) kullanarak jhplot.Web sınıfını kullanarak (fastutil-8.2.2.jar için basit bir örnek ) olarak yapabilirim

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

Belgelere göre, bu dosya "lib / user" içine indirilecek ve daha sonra dinamik olarak yüklenecektir, böylece aynı jar dosyasındaki bu jar dosyasındaki sınıfları hemen kullanmaya başlayabilirsiniz.


1

Java 8 ve java 9+ için çalışma zamanında bir jar dosyası yüklemem gerekiyordu (yukarıdaki yorumlar bu sürümlerin her ikisi için de çalışmıyor). İşte bunu yapmak için bir yöntem (eğer ilgili ise Spring Boot 1.5.2 kullanarak).

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());
    }
}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.