【问题标题】:Custom ClassLoader, how to use?自定义ClassLoader,怎么用?
【发布时间】:2019-03-26 16:01:20
【问题描述】:

我正在尝试使用自定义类加载器来加载应用程序所需的所有依赖项。我已经在该站点之后实现了 customerClassLoader:https://www.javacodegeeks.com/2013/03/java-handmade-classloader-isolation.html

但是,我不明白如何告诉我的应用程序在需要时使用自定义类加载器。

例如:可以说,我有一种方法可以发出如下的 http 请求。如何告诉应用程序使用自定义的 classLoader 来加载所需的 jar?

private HttpResponse get() {
    HttpClient client = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet(url);
    HttpResponse response = client.execute(request);
    return response;
}

【问题讨论】:

    标签: java classloader dynamic-class-loaders


    【解决方案1】:

    Java隐式使用ClassLoader当你使用new,import关键字时,jvm会使用当前类的类加载器来加载依赖类,所以你可以使用自定义类加载器显式加载一个bootstrap类通过使用classloader.loadclassbootstrap 只是运行属于您的目标类实例的方法。下面是一个例子。

    有一个类Target 依赖于包含在spring-context 中的类DateFormatter,并且有一个名为start 的方法。

    import org.springframework.format.datetime.DateFormatter;
    
    public class Target {
    
    private static DateFormatter dateFormatter;
    
    public void start(){
        System.out.println(this.getClass().getClassLoader());
        dateFormatter=new DateFormatter();
        System.out.println(dateFormatter);
        }
    }
    

    接下来,我们将上面的代码编译打包成一个名为target.jar的jar,存放在D:\\test\\target.jar

    接下来,我们在另一个 jar 中声明一个类 BootStrap,它将调用 Target 实例的方法 startBootStrap 类将通过相同的classloader 动态加载target.jarspring-context jar 文件,这是一个URLClassLoader 实例。因此,Target 实例中的方法start 可以访问spring-context 中定义的DateFormatter 类。

    public class BootStrap {
    
    
    public static void main(String[] args) throws Exception{
        URL url = new URL("http://maven.aliyun.com/nexus/content/groups/public/org/springframework/spring-context/4.3.1.RELEASE/spring-context-4.3.1.RELEASE.jar?spm=0.0.0.0.kG1Pdw&file=spring-context-4.3.1.RELEASE.jar");
        URL url2= (new File("D:\\test\\target.jar").toURI().toURL());
        URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2});
        Class<?> clz = classLoader.loadClass("com.zhuyiren.Target");
        Object main = clz.newInstance();
        Method test = clz.getMethod("start");
        test.invoke(main);
        }
    }
    

    最后,运行BootStrap main 方法。有两点很重要:

    1. BootStrap 类和Target 类不属于同一个 jar 文件。
    2. target.jar 未存储在 CLASSPATH 路径中。

    这2点可以确保AppClassLoader无法找到并加载Target类。因为类加载器的机制,jvm会使用自定义加载Target。当然,你可以通过将URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2});改为URLClassLoader classLoader = new URLClassLoader(new URL[]{url, url2}, ClassLoader.getSystemClassLoader().getParent()); 来保证

    我们可以看到结果:

    java.net.URLClassLoader@e9e54c2
    org.springframework.format.datetime.DateFormatter@4dd8dc3
    

    这意味着我们可以成功访问定义在spring-context jar 文件中的DateFormatter 实例,而spring-context 没有存储在CLASSPATH 中,但是我们使用自定义的类加载器来加载和使用它。

    【讨论】:

      【解决方案2】:

      您可以执行以下操作;

      Thread.currentThread().setContextClassLoader(new MyCustomClassLoader());
      

      【讨论】:

      猜你喜欢
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2015-11-15
      相关资源
      最近更新 更多