在罐子里加载一个外部库

问题描述

我有一个动态加载的jar文件, 在它里面有lib /我在main(导入it.xxx.xx)中使用的另一个jar(外部库)。 如何在classpath中动态加载此外部库? 我的代码不起作用:

public static void runOne(String jar,String class_name,Optional<String> test_name,TestExecutionListener listener) throws Exception {
        Launcher launcher = LauncherFactory.create();
        
        ClassLoader loader = URLClassLoader.newInstance(
                new URL[] { new File(pathJars+"/"+jar).toURI().toURL() },ServiceUtil.class.getClassLoader()
        );

        loader.getClass(); 

        addURL(loader); <--here i want add a jar to classpath!

        Class cls=loader.loadClass(class_name);
        Constructor constructor = cls.getConstructor();
        constructor.newInstance();

        LauncherDiscoveryRequest request;
        if (test_name.isPresent()) {
            Method m = cls.getMethod(test_name.get());
            request = LauncherDiscoveryRequestBuilder.request()
                    .selectors(selectMethod(cls,m))
                    .build();
        }
        else{
            request = LauncherDiscoveryRequestBuilder.request()
                    .selectors(selectClass(cls))
                    .build();
        }

        TestPlan testPlan = launcher.discover(request);
        launcher.registerTestExecutionListeners(listener);
        launcher.execute(request);
        //launcher.execute(request);
        loader=null;
        System.gc();

    }
    public static void addURL(ClassLoader loader) throws IOException {
        URL u=loader.getResource("lib/sem-platform-sdk-1.0-SNAPSHOT.jar");
        Class[] parameters = new Class[]{URL.class};
        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");
        }//end try catch

    }//end method

谢谢

解决方法

通常使用构建工具(例如Maven或Gradle)完成此操作。我不知道您是否正在使用其中之一。它们使生活变得更加轻松。

我们将Maven与Apache Shade插件配合使用来实现此目的。 Maven具有自动为您设置配置的命令,然后将Shade插件添加到生成的配置文件(pom.xml)中。

https://maven.apache.org/plugins/maven-shade-plugin/index.html

,

如果我正确理解了您的问题,则希望从jar文件加载的类能够访问嵌套jar文件中的类。您可以通过创建ClassLoader来实现此目的,该类加载器的jar文件的一个条目和嵌套jar文件的另一个条目。

Java有一个特殊的URL方案jar:,用于直接引用jar条目。 (此方案和语法在the documentation of JarURLConnection中进行了描述。)因此,您可以按以下方式构造ClassLoader:

    URL jarURL = new File(pathJars+"/"+jar).toURI().toURL();
    URL semURL = new URL("jar:" + jarURL + "!/"
        + "lib/sem-platform-sdk-1.0-SNAPSHOT.jar");

    ClassLoader loader = URLClassLoader.newInstance(
            new URL[] { jarURL,semURL },ServiceUtil.class.getClassLoader()
    );

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...