博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JVM 类加载器
阅读量:1826 次
发布时间:2019-04-25

本文共 1614 字,大约阅读时间需要 5 分钟。

一、字节码与运行时程序的关系:

写好的代码经过编译变成了字节码,并且可以打包成Jar文件。 然后就可以让JVM去加载需要的字节码,变成持久代/元数据区上的Class对象,接着才会执行我们的程序逻辑。

 

二、类的生命周期和加载过程

一个类的生命周期包括以下几个方面:

  1. 加载
  2. 验证
  3. 准备
  4. 解析
  5. 初始化
  6. 使用
  7. 卸载

在这些过程中,1-5步骤被称作类加载。

 

三、类加载时机

提到类加载时机,有个细节需要记录的是:类会在哪些情况下被初始化?这里记录下一些情况。

初始化何时会被触发:

  • 当虚拟机启动时,初始化用户指定的主类,就是启动执行的 main方法所在的类;
  • 当遇到用以新建目标类实例的new指令时,初始化new指令的目标类,就是new一个类的时候要初始化。
  • 当遇到调用静态方法的指令时,初始化该静态方法所在的类
  • 当遇到访问静态字段的指令时,初始化该静态字段所在的类
  • 子类的初始化会触发父类的初始化
  • 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;
  • 使用反射API对某个类进行反射调用时,初始化这个类,其实跟前面一样,反射调用要么是已经有实例了,要么是静态方法,都需要初始化
  • 当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类。

 

同时以下几种情况不会执行类初始化:

  • 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
  • 定义对象数组,不会触发该类的初始化
  • 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。
  • 通过类名获取Class对象,不会触发类的初始化,Hello.class不会让Hello类初始化
  • 通过Class.forName加载指定类时,如果指定参数initialize为false时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。Class.forName(“jvm.Hello”)默认会加载Hello类。
  • 通过ClassLoader默认的loadClass方法,也不会触发初始化动作(加载了,但是不初始化)

 

四、类加机制

类加载器有以下几个:

  • 启动类加载器(BootstrapClassLoader)
  • 扩展类加载器(ExtClassLoader)
  • 应用类加载器(AppClassLoader)

其中扩展类加载器(ExtClassLoader)和 应用类加载器(AppClassLoader)都是继承RLClassLoader类。

这里有一个小细节就是,String类是由哪个加载器加载的。答案是:java.lang.String是由启动类加载器加载的,所以String.class.getClassLoader()就会返回null。

 

类加载机制有三个特点:

  1. 双亲委托:当一个自定义类加载器需要加载一个类,比如java.lang.String,它很懒,不会一上来就直接试图加载它,而是先委托自己的父加载器去加载,父加载器如果发现自己还有父加载器,会一直往前找,这样只要上级加载器,比如启动类加载器已经加载了某个类比如java.lang.String,所有的子加载器都不需要自己加载了。如果几个类加载器都没有加载到指定名称的类,那么会抛出ClassNotFountException异常。
  2. 负责依赖:如果一个加载器在加载某个类的时候,发现这个类依赖于另外几个类或接口,也会去尝试加载这些依赖项。
  3. 缓存加载:为了提升加载效率,消除重复加载,一旦某个类被一个类加载器加载,那么它会缓存这个加载结果,不会重复加载。

 

五、总结:

  • 介绍了类加载的机制,以及类的生命周期。
  • 接着我们介绍了,在那种情况下会初始化类,哪些情况下不会。
  • 介绍了类加载器,这部分是老生常谈的东西。不过有一个小细节需要留心就是:String是谁加载的。
  • 介绍了类加载特点。

 

转载地址:http://lovkf.baihongyu.com/

你可能感兴趣的文章
Linux基础之常用系统管理命令(四)
查看>>
Python批量转换txt文本为xlsx
查看>>
Linux常用服务器软件之ftp(一)
查看>>
Linux常用服务器软件之samba(二)
查看>>
Centos yum安装mysql5.7.30
查看>>
Centos 离线安装mysql5.7.32
查看>>
面试技巧总结
查看>>
centos7下安装Python3.6和pip
查看>>
oracle创建表空间自增长和创建用户
查看>>
配置Linux主机SSH无密码访问
查看>>
centos7升级内核到5.10.7-1
查看>>
centos7源码安装、部署Zabbix4监控平台
查看>>
ADO.NET实用经验汇总
查看>>
VMS中解协议常用方法备忘
查看>>
获取客户端IP地址-考虑代理
查看>>
用什么方法将BitConverter.ToString产生字符串再转换回去
查看>>
[网络收集]利用Session对象实现购物车
查看>>
线程5种状态-详细
查看>>
多线程编程技术基础知识
查看>>
多线程对资源读写时如何控制
查看>>