加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

Java的神秘世界:为何说ClassLoader 是 Java最神秘的技术之一

发布时间:2019-10-16 20:07:44 所属栏目:建站 来源:java互联网高级架构
导读:ClassLoader 是 Java 届最为隐秘的技能之一,无数人被它伤透了思维,摸不清门道毕竟在那边。网上的文章也是一篇又一篇,颠末本人的亲身判断,绝大部门内容都是在误导别人。本文我带读者彻底吃透 ClassLoader,往后其余的相干文章你们可以不必再细看了。 Cl

项目打点上有一个闻名的观念叫着「钻石依靠」,是指软件依靠导致统一个软件包的两个版本必要共存而不能斗嘴。

Java的隐秘天下:为何说ClassLoader 是 Java最隐秘的技能之一

我们平常行使的 maven 是这样办理钻石依靠的,它会从多个斗嘴的版本中选择一个来行使,假如差异的版本之间兼容性很糟糕,那么措施将无法正常编译运行。Maven 这种情势叫「扁平化」依靠打点。行使 ClassLoader 可以办理钻石依靠题目。差异版本的软件包行使差异的 ClassLoader 来加载,位于差异 ClassLoader 中名称一样的类现实上是差异的类。下面让我们行使 URLClassLoader 来实行一个简朴的例子,它默认的父加载器是 AppClassLoader

  1. $ cat ~/source/jcl/v1/Dep.java 
  2. public class Dep { 
  3.     public void print() { 
  4.         System.out.println("v1"); 
  5.     } 
  6. $ cat ~/source/jcl/v2/Dep.java 
  7. public class Dep { 
  8.  public void print() { 
  9.  System.out.println("v1"); 
  10.  } 
  11. $ cat ~/source/jcl/Test.java 
  12. public class Test { 
  13.     public static void main(String[] args) throws Exception { 
  14.         String v1dir = "file:///Users/qianwp/source/jcl/v1/"; 
  15.         String v2dir = "file:///Users/qianwp/source/jcl/v2/"; 
  16.         URLClassLoader v1 = new URLClassLoader(new URL[]{new URL(v1dir)}); 
  17.         URLClassLoader v2 = new URLClassLoader(new URL[]{new URL(v2dir)}); 
  18.          
  19.  Class<?> depv1Class = v1.loadClass("Dep"); 
  20.         Object depv1 = depv1Class.getConstructor().newInstance(); 
  21.         depv1Class.getMethod("print").invoke(depv1); 
  22.         Class<?> depv2Class = v2.loadClass("Dep"); 
  23.         Object depv2 = depv2Class.getConstructor().newInstance(); 
  24.         depv2Class.getMethod("print").invoke(depv2); 
  25.       
  26.  System.out.println(depv1Class.equals(depv2Class)); 
  27.  } 

在运行之前,我们必要对依靠的类库举办编译

  1. $ cd ~/source/jcl/v1 
  2. $ javac Dep.java 
  3. $ cd ~/source/jcl/v2 
  4. $ javac Dep.java 
  5. $ cd ~/source/jcl 
  6. $ javac Test.java 
  7. $ java Test 
  8. v1 
  9. v2 
  10. false 

在这个例子中假如两个 URLClassLoader 指向的路径是一样的,下面这个表达式照旧 false,由于纵然是同样的字节码用差异的 ClassLoader 加载出来的类都不能算统一个类

  1. depv1Class.equals(depv2Class) 

我们还可以让两个差异版本的 Dep 类实现统一个接口,这样可以停止行使反射的方法来挪用 Dep 类内里的要领。

  1. Class<?> depv1Class = v1.loadClass("Dep"); 
  2. IPrint depv1 = (IPrint)depv1Class.getConstructor().newInstance(); 
  3. depv1.print() 

ClassLoader 当然可以办理依靠斗嘴题目,不外它也限定了差异软件包的操纵界面必需行使反射或接口的方法进动作态挪用。Maven 没有这种限定,它依靠于假造机的默认懒惰加载计策,运行进程中假如没有表现行使定制的 ClassLoader,那么从新到尾都是在行使 AppClassLoader,而差异版本的同名类必需行使差异的 ClassLoader 加载,以是 Maven 不能美满办理钻石依靠。 假如你想知道有没有开源的包揽理器材可以办理钻石依靠的,我保举你相识一下 sofa-ark,它是蚂蚁金服开源的轻量级类断绝框架。

分工与相助

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读