Mám aplikaci, která načítá soubory jar v běhu dynamicky pomocí následujících řešení:
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);
To bylo provedeno pomocí odpověď na to, Jak nahrát JAR soubory dynamicky za Běhu?
Nyní chci řešení, které funguje JDK11+, který je ekvivalentní k původnímu řešení, které jsem použil. Tak to dělá programově, bez nutnosti knihoven třetích stran/rámců nebo načítání/vyvolání jedné třídy.
Zkoušel jsem následující:
- Vytvořil DynamicClassLoader, který rozšiřuje UrlClassLoader:
public final class DynamicClassLoader extends URLClassLoader {
public DynamicClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public DynamicClassLoader(String name, ClassLoader parent) {
super(name, new URL[0], parent);
}
public DynamicClassLoader(ClassLoader parent) {
this("classpath", parent);
}
public void addURL(URL url) {
super.addURL(url);
}
}
- Pak jsem se začít svou žádost vtip java.systém.třídy.nakladač flag:
java -Djava.system.class.loader=com.example.DynamicClassLoader
Pak mám soubor jar jako cesta objektu, který mám následující metodu:
public void loadJar(Path path) throws Exception {
URL url = path.toUri().toURL();
DynamicClassLoader classLoader = (DynamicClassLoader)ClassLoader.getSystemClassLoader();
Method method = DynamicClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, url);
}
Když tato metoda je volána jsem si následující obsazení třídy výjimka:
class jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to class com.example.classloader.DynamicClassLoader (jdk.internal.loader.ClassLoaders$AppClassLoader is
in module java.base of loader 'bootstrap'; com.example.classloader.DynamicClassLoader is in unnamed module of loader 'app')
Já používám Spring Boot (2.4) na OpenJDK11 (build 11.0.10+9).
URLClassLoader
měla by se zobrazit JAR Url, ne jednotlivých tříd, tak jako to děláš tady. Pouze jednu třídu loader stupně by měly být vytvořeny tak, aby zatížení třídy z jar (nebo mnoho). Poznamenal jsem o tom ve své GitHub úložiště.