《深入理解java虚拟机》笔记——3.类加载

什么时候加载一个类?

  1. new一个对象;调用类的静态方法或静态属性;
  2. 使用反射获取类信息;
  3. 初始化一个对象,会先初始化其父类;
  4. Jvm启动,即当前java程序启动时必须调用主类的 main() 方法,主类会先加载;

类加载过程?(5步)

  1. 加载;加载类的.class文件,生成Class对象(单例对象);
  2. 验证;检查.class文件的二进制字节流,完成“文件格式、元数据、字节码”等的验证;
  3. 准备;仅仅为“类变量”初始化;
  4. 解析;将常量池的符号引用替换为直接引用;
  5. 初始化;真正的执行java代码的初始化部分;

类加载器分类?(4种,从上往下)

  1. 启动类加载器,C++代码实现,加载 /lib/ 路径下的类库;
  2. 扩展类加载器,由Extra Class Loader实现,加载 /lib/ext/ 路径下的类库;
  3. 应用程序类加载器,由App Class Loader实现,加载ClassPath路径下的类库;为“默认类加载器”;
  4. 自定义类加载器;

双亲委派模型?为什么?

image.jpeg

双亲委派模型规定,除了最顶层的启动类加载器,类加载器都必须有其“父类加载器”;(父子关系通过“组合”方式实现,而非“继承”)

原理:当一个类加载器收到“去加载一个类”的请求时,会先把这个请求“委派”给其父类类加载器;这样无论哪个层的类加载器,加载请求最终都会委派给顶层的启动类加载器,启动类加载器在其目录下尝试加载该类,找不到该类,子加载器才会自己尝试加载这个类;

为什么?保证加载的类的唯一性;例如 java.lang.Object类,在 /lib/目录下的rt.jar 内,无论哪个类加载器去加载这个类,他们最终都是调用“启动类加载器”加载,即加载的类是同一个类;否则每个类加载器都有自己的“加载路径”,若有重名的类,则会导致程序混乱;

FindClass与 LoadClass ?(对于自定义类加载器)

  • LoadClass:自定义类加载器,重写loadClass() 方法,可以让不同的类加载器保留各自的“同名的类”,工作流程是先自己尝试加载这个类,加载成功则返回,加载失败才会交给父类加载器;即“破坏了双亲委派模型和类的唯一性”;

例如:有一个插件容器,现在需要往里面添加A、B两个插件。A、B两个插件都定义了一个“相同名字”的类,如Test.class ,由于A、B插件在定义时都不知道彼此的信息,各自定义的Test类有具有不同的功能,因此“有必要加载这两个具有不同功能的重名的类”;使用“双亲委派模型”只会加载一次,只加载其中一个Test类;

  • FindClass:符合“双亲委派模型”,保证一个类只会加载一次;在JDK源码中,findClass() 方法是放在 catch{...} 块内的,因此一般情况是用不到这个方法的;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值