自定义ClassLoader,如何使用? - java

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

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

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

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

参考方案

当您使用ClassLoadernew关键字时,Java会隐式使用import,JVM将使用当前类的类加载器来加载相关类,因此您可以使用自定义类加载器通过使用bootstrap显式加载classloader.loadclass类,而bootstrap只是运行一个方法属于您的目标类实例。下面是一个示例。

有一个Target类,它取决于DateFormatter中包含的spring-context类,并且有一个名为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类,该类将调用start实例的Target方法。 BootStrap类将通过作为target.jar实例的相同spring-context动态加载classloaderURLClassLoader jar文件。因此,start实例中的Target方法可以访问DateFormatter中定义的spring-context类。

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方法。有两个重要的事情:

  • BootStrap类和Target类不属于同一个jar文件。
  • 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
    

    这意味着我们可以成功访问DateFormatter jar文件中定义的spring-context实例,而spring-context并不存储在CLASSPATH中,但是我们正在使用自定义的clasloader进行加载和使用。

    Java:静态字段在内存中的哪个位置? - java

    如果我们将对象存储在对象的静态字段中,那么JVM如何为它分配内存?它是否存在于“隐式”(不确定我是否使用正确的单词)类对象中?静态字段与对象字段有何不同? 参考方案 静态字段是类变量,并且在该类的所有实例之间共享。实例变量(或我认为您引用它们的对象字段)属于类的各个实例,并且不共享。至于它们存储在内存中的位置将根据JVM的实现而定,因此没有理由需要两个不同的…

    Java-非泛型类扩展了泛型类 - java

    我想知道如何(如果可能)创建一个类,它是泛型类的特定类型。具体来说,我有一个实现所有必需方法的abstract class Stack<Type>,我想有一个class StackInteger,而StackInteger的实例也是Stack<Integer>的实例。我看到我可以做这样的事情:class StackInteger { …

    Java:正则表达式模式匹配器是否有大小限制? - java

    我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…