专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
Java编程精选  ·  阿里员工吐槽:80%以上的leader认为, ... ·  2 天前  
Java编程精选  ·  公司Rust团队全员被裁,只因把服务写得「太 ... ·  7 小时前  
芋道源码  ·  别乱分层,PO、VO、DAO、BO、DTO、 ... ·  15 小时前  
芋道源码  ·  谈一谈 分库分表 vs NewSQL数据库 ·  昨天  
芋道源码  ·  一款轻便、安全、免费的远程桌面工具 ·  昨天  
51好读  ›  专栏  ›  ImportNew

完全理解双亲委派模型与自定义 ClassLoader

ImportNew  · 公众号  · Java  · 2017-04-01 12:09

正文

请到「今天看啥」查看全文



  • 扩展类加载器(Extension ClassLoader):负责加载 \lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。


  • 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。


双亲委派模型工作过程是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。

类加载器的双亲委派模型


1.2 为什么需要双亲委派模型?


为什么需要双亲委派模型呢?假设没有双亲委派模型,试想一个场景:


黑客自定义一个java.lang.String类,该String类具有系统的String类一样的功能,只是在某个函数稍作修改。比如equals函数,这个函数经常使用,如果在这这个函数中,黑客加入一些“病毒代码”。并且通过自定义类加载器加入到JVM中。此时,如果没有双亲委派模型,那么JVM就可能误以为黑客自定义的java.lang.String类是系统的String类,导致“病毒代码”被执行。


而有了双亲委派模型,黑客自定义的java.lang.String类永远都不会被加载进内存。因为首先是最顶端的类加载器加载系统的java.lang.String类,最终自定义的类加载器无法加载java.lang.String类。


或许你会想,我在自定义的类加载器里面强制加载自定义的java.lang.String类,不去通过调用父加载器不就好了吗?确实,这样是可行。但是,在JVM中,判断一个对象是否是某个类型时,如果该对象的实际类型与待比较的类型的类加载器不同,那么会返回false。


举个简单例子:


ClassLoader1、ClassLoader2都加载java.lang.String类,对应Class1、Class2对象。那么Class1对象不属于ClassLoad2对象加载的java.lang.String类型。


1.3 如何实现双亲委派模型?


双亲委派模型的原理很简单,实现也简单。每次通过先委托父类加载器加载,当父类加载器无法加载时,再自己加载。其实ClassLoader类默认的loadClass方法已经帮我们写好了,我们无需去写。


2. 自定义类加载器


2. 1几个重要函数


2.1.1 loadClass


loadClass默认实现如下:


public Class> loadClass(String name) throws ClassNotFoundException {

return loadClass(name, false);

}


再看看loadClass(String name, boolean resolve)函数:


protected Class> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

synchronized (getClassLoadingLock(name)) {

// First, check if the class has already been loaded

Class c = findLoadedClass(name);

if (c == null) {

long t0 = System.nanoTime();

try {







请到「今天看啥」查看全文