clssloader与双亲委派

JVM里的有几种classloader,为什么会有多种?

什么是双亲委派机制?介绍一些运作过程,双亲委派模型的好处;

什么情况下我们需要破坏双亲委派模型;

常见的JVM调优方法有哪些?可以具体到调整哪个参数,调成什么值?

https://blog.csdn.net/briblue/article/details/54973413

Java装载类使用“全盘负责委托机制”。“全盘负责”是指当一个ClassLoder装载一个类时,除非显示的使用另外一个ClassLoder,该类所依赖及引用的类也由这个ClassLoder载入;“委托机制”是指先委托父类装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。这一点是从安全方面考虑的,试想如果一个人写了一个恶意的基础类(如java.lang.String)并加载到JVM将会引起严重的后果,但有了全盘负责制,java.lang.String永远是由根装载器来装载,避免以上情况发生 除了JVM默认的三个ClassLoder以外,第三方可以编写自己的类装载器,以实现一些特殊的需求。类文件被装载解析后,在JVM中都有一个对应的java.lang.Class对象,提供了类结构信息的描述。数组,枚举及基本数据类型,甚至void都拥有对应的Class对象。Class类没有public的构造方法,Class对象是在装载类时由JVM通过调用类装载器中的defineClass()方法自动构造的。

类加载

ClassLoader 顾名思义就是类加载器,ClassLoader 作用:

  • 负责将 Class 加载到 JVM 中
  • 审查每个类由谁加载(父优先的等级加载机制)
  • 将 Class 字节码重新解析成 JVM统一要求的对象格式
    在这里插入图片描述

什么情况下需要开始类加载过程的第一个阶段:”加载”。虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握,但是对于初始化阶段虚拟机规范是严格规定了如下几种情况,如果类未初始化会对类进行初始化:

  1. 创建类的实例
  2. 对类进行反射调用的时候,如果累没有进行过初始化,则需要先触发其初始化
  3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
  4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main 方法的那个类),虚拟机会先初始化这个主类
  5. 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。

其余的其他情况,称为被动引用,都不会触发类的初始化。下面也举了些被动引用的例子:
1.构造某个类的数组时并不会导致类的初始化,比如下面的例子:

public static void main(String[] args){
    Simple[] simples = new Simple[10];
    System.out.println(simples.length);
}

该操作只不过是在堆内存中开辟了一段连续的地址空间4byte x 10。

2.引用类的静态常量不会导致类的初始化

常量在编译阶段会存入调用类的常量池

3.jdk:1.8 通过子类引用父类的静态字段,不会导致子类初始化

class  SuperClass{
    static {
        System.out.println("SuperClass init!");
    }
    public  static  int value=123;
}
class  SubClass extends  SuperClass{
    static {
        System.out.println("SubClass init!");
    }
}

public class Test {
    public static void main(String[] args)throws  Exception{
      System.out.println(SubClass.value); 
      //输出:
      //SuperClass init!
      //123
    }
}

通过其子类来引用父类中定义的静态字段,只会触发父类初始化而不会触发子类的初始化。至于是否要触发子类的加载和验证,这个在虚拟机规范中并没有明确规定,这点取决于虚拟机的具体实现。
在这里插入图片描述
在这里插入图片描述
https://segmentfault.com/a/1190000013469223#articleHeader7

破坏双亲委派模型

双亲委派模型并不是一个强制性的约束模型,在java的世界中大部分的类加载器都遵循这个模型,但也有例外,一个典型的例子便是JNDI服务。

JNDI存放于rt.jar,由启动类加载器加载,JNDI的目的是对资源进行集中管理和查找,它需要调用由各厂商实现并部署在应用程序ClassPath下的JNDI接口实现的代码,如此一来,在双亲委派模型下,启动类加载器根本无法加载这些代码

针对此问题,java设计团队引入了线程上下文类加载器(Thread Context ClassLoader),这个类加载器可以通过Thread类的setContextClassLoader进行设置,默认继承父线程类加载器
通过线程上下文类加载器,JNDI服务通过此类加载器,由父类加载器请求子类加载器完成类加载动作

破坏双亲委派模型的例子还有很多,如tomcat服务、osgi、jigsaw等等,是否破坏双亲委派模型并没有对与错,只是不同场景下的具体应用而已

类的唯一性

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值