类加载器、双亲委派机制与线程上下文类加载器

首先介绍java类加载器:

1. boostrap classloader:根类加载器,用来加载JAVA_HOME/lib文件夹下的java核心类,由C++实现,不是ClassLoader的子类。不继承自java.lang.ClassLoader。由于boostrap类加载器涉及到虚拟机本地实现细节,因此开发者无法直接获取boostrap 类加载器的引用。(获取返回null)通过-Xbootclasspath可以设置bootclasspath的加载路径

2. extension ClassLoader:拓展类加载器,用来加载lib/ext文件夹下的jar包(必须是jar包形式存),父加载器为null。

3. Application ClassLoader:应用程序类加载器,也叫系统类加载器,用来加载用户路径上的指定类库。自己编写的代码和第三方jar包都是由它加载。

其次是双亲委派机制:

当类加载器收到一个类加载请求时,先检查自己是否加载过该类findLoadedClass(name),否则将请求委派给父类类加载器,父类加载器同样,先检查自己是否加载过该类,没有的话则委派,若没有上级,则委派给启动类加载器findBoostrapClassOrNull(name),当父类无法完成加载,则调用每个类加载器的findClass()方法来加载。这样避免了子加载器加载一些试图冒名顶替可信任类的不可靠类,也不会让子加载器去实现父加载器实现的加载工作。

不同命名空间的类无法相互调用。

类加载体系为不同类加载器加载的类提供不同的命名空间,同一命名空间内的类可以互相访问,不同命名空间的类不知道彼此的存在(除非显式提供访问机制)。同一类可以再不同的命名空间内,但无法在同一命名空间内重复出现。

命名空间是这样定义的:实际完成加载类的工作的加载器为定义类加载器,而加载的双亲委托路径上的所有加载器为初始类加载器,某个加载器的命名空间就是所有以该加载器为初始类加载器的类所组成。

可以预见,子加载器的命名空间包括其父/祖先加载器的命名空间和只有自己才可以加载的类所组成。根据加载体系结构的安全机制,同一命名空间内的类可 以互相访问,所以父加载器所加载的类不一定可以访问子加载器所加载的类,但子加载器所加载的类必然可以访问父加载器加载的类。父加载器加载的类就好像小箱 子,子加载器加载的类可能用到父加载器加载的类,就像一个大箱子,只能把小箱子放进大箱子,而不能反过来做(当然显式的访问机制除外)

首先为什么需要双亲委派机制?

答:双亲委派机制使得类的加载出现层级,父类加载器加载过的类,子类加载器不会重复加载.可以防止类的重复加载.使得类的加载出现优先级,防止核心API被篡改,提供了安全方面的考量.所以越基础的类就会越上层进行加载.

打破双亲委派与如何打破:

在一些应用中需要人为打破双亲委派机制。例如加载数据库驱动时,JDBC的核心在rt.jar中由启动类加载器加载,而数据库驱动的第三方实现往往以jar包的形式存在于classpath下(即应用程序类加载器负责加载)。当boostrap类加载器尝试实例化第三方数据库的实现类时,会报错。

如何打破?

1. 自定义类加载器,重写loadClass方法

2. 使用线程上下文类加载器。这个类加载器可以通过java.lang.Thread类的setContextClassLoader方法进行设置,如果创建线程时还没有设置,则从父线程中继承一个cl,如果父线程也未设置,则默认使用应用程序类加载器。


 

参考文章:实例分析JVM安全体系:双亲委派、命名空间、保护域、策略_daniel7443的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值