java虚拟机类加载
java虚拟机中类的加载

(JVM的大致结构图)
从发class文件到内存中的类,按先后顺序,需要经过加载,链接以及初始化三大步骤。
java语言的类型可分为两大类:基本类型(primitive type)和引用类型(references type)
基本类型:是由java虚拟机预先定义好的。
引用类型:Java将其细分为四种,类、接口、数组类和泛型参数。
由于泛型参数会在编译过程中被擦除(泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型。),因此Java虚拟机实际上只有前三种。在类、接口和数组类中,数组类是由java虚拟机直接生成的,其他两种则有对应的字节流。
字节流:最常见的形式要属由Java编译器生成的class文件。除此之外,我们也可以在程序内部直接生成,或者从网络中获取字节流。这些不同形式的字节流,都会被加载到java虚拟机中,称为类或者接口。
无论是直接生成的数组类,还是加载的类,java虚拟机都要对其进行链接和初始化。
加载
加载是指查找字节流,并且据此创建类的过程。对于类来说,java虚拟机需要借助类加载器来完成查找字节流的过程。
当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:
1、启动类加载器(BootstrapClassLoader):是嵌在JVM内核中的加载器,它是由C++实现的,没有对应的java对象,因此在java中只能用null来代替。它主要负责加载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。
除了启动类加载器外,其他的类加载器都是java.lang.ClassLoader的子类,因此有对应的java对象。这些类加载器需要先由另一个类加载器,比如说启动了加载器,加载至java虚拟机中,方能执行类加载。
在Java9之前,启动类加载器负责加载最为基础,最为重要的类,比如存放在jre的lib目录下的jar包(以及由虚拟机参数-Xbootclasspath指定的类)。除了启动类加载器之外,另外两个重要的类加载器是扩展类加载起(extension class loader)和应用类加载器(application class loader),均由java核心类库提供。
2、扩展类加载器(extension class loader):其父类是启动类加载器,他负责加载相对次要、但又通用的类,比如存放在jre的lib/ext目录下的jar包中的类(以及由系统变量java.ext.dirs指定的类)。
3、应用类加载器(application class loader):其父类是扩展类加载器,它负责加载用用程序下的类。(这里的应用程序路径,便是指虚拟机参数-cp/-classpath、系统变量CLASSPATH所制定的路径。)默认情况下,应用程序中包含的类是由应用类加载器加载的。
java9引入了模块系统,,并且略微更改了上述的类加载器,扩展类加载器被改名为平台类加载器(platform class loader)。Java SE 中除了少数几个关键模块,比如说、java.base是由启动类加载器加载之类,其他的模块均由平台加载器所加载。
除了java核心类库提供的类加载器之外,我们还可以加入自定义的加载器,来实现特殊的加载方式。举个例子,我们可以对class文件进行加密,加载时再利用自定义的类加载最其解密。
除了加载功能之外,类加载器还提供了命名空间的作用。在java虚拟机中,类的唯一性是由类加载器实例以及类的全名一同确定的。即便是通一串字节流,经由不同的类加载器加载,也会得到两个不同的类。在大型应用中,我们往往会借助这一特性,来运行同一个类的不同版本。
链接
链接是指将创建成的类合并至java虚拟机中,使之能执行的过程。它可以分为验证、准备及解析三个阶段。
验证:确保被加载的类能够满足java虚拟机的约束条件,检验被加载的类是否有正确的内部结构,并和其他类协调一致。
准备:为被加载类的静态字段分配内存,并设置默认初始值。
解析:将类中的二进制数据中的符号引用替换成直接引用(final修改的常量的替换)。
JVM并没有要你在链接过程中完成解析,它仅规定了:如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成对这些符号引用的解析。
初始化
在java代码中如果要初始化一个静态字段,我们可以在声明时直接赋值,也可以在静态代码块中对其赋值。
如果直接赋值的静态字段被final修饰,并且他的类型是基本类型或字符串时,那么该字段便会被java编译器标记为常量值(ConstantValue),其初始化直接被java虚拟机完成。除此之外的直接赋值操作以及所有静态代码块中的代码,则会被java编译器置于同一方法中,并把它命名为<clinit>。
类加载的最后一步是初始化,便是为标记为常量值的字段赋值,以及执行<clinit>方法的过程。java虚拟机会通过加锁来确保类的<clinit>方法仅被执行一次。
只有当初始化完成之后,类才正式称为可执行的状态。
JVM初始化一个类分为几步:
1、假如这个类还没有被加载和链接,程序先加载并链接这个类。
2、假如该类的直接父类还没有被初始化,则先初始化其直接父类。
3、假如类中有初始化语句,则依次执行其初始化语句。
类的加载和初始化何时被触发
1、当虚拟机启动时,初始化用户指定的主类。(直接使用java.exe命令来运行某个主类)
2、创建类的实例(new方法)。
3、调用某个类的静态方法,初始化该静态方法所在的类。
4、访问某个类或接口的静态属性,初始化该静态属性所在的类。
5、使用反射机制来创建某个类或接口的对应java.lang.Class对象(Class.forName("Person")),初始化这个类。
6、子类的初始化会触发父类的初始化。
7、如果一个接口定义了default方法,那么直接实现或间接实现该接口的类的初始化,会触发该接口的初始化。
8、当初次使用MehodHandle实例时,初始化该MehodHandle指向的方法所在的类。
注:此文为极客时间郑雨迪专栏,java虚拟机讲解及自己查资料的学习总结。郑雨迪《深入拆解Java虚拟机》很不错。
java虚拟机类加载的更多相关文章
- Java虚拟机类加载机制——案例分析
转载: Java虚拟机类加载机制--案例分析 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...
- 深入理解Java虚拟机---类加载机制(简略版)
类加载机制 谈起类加载机制,在这里说个题外话,当初本人在学了两三个月的Java后,只了解了一些皮毛知识,就屁颠屁颠得去附近学校的招聘会去蹭蹭面试经验,和HR聊了一会后开始了技术面试,前抛出了两个简单的 ...
- 面试官,不要再问我“Java虚拟机类加载机制”了
关于Java虚拟机类加载机制往往有两方面的面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断程 ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- [转]Java虚拟机类加载机制
原文地址:http://blog.csdn.net/u013256816/article/details/50829596 看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎 ...
- java虚拟机类加载机制和双亲委派模型
java虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型. 类的生命周期是从类被加载到虚拟机内存中,到卸 ...
- 面试官,不要再问我“Java虚拟机类加载机制”了(转载)
关于Java虚拟机类加载机制往往有两方面的 面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断 ...
- JVM(三)-java虚拟机类加载机制
概述: 上一篇文章,介绍了java虚拟机的运行时区域,Java虚拟机根据不同的分工,把内存划分为各个不同的区域.在java程序中,最小的运行单元一般都是创建一个对象,然后调用对象的某个 方法.通过上一 ...
- 【转载】Java虚拟机类加载机制与案例分析
出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...
- Java虚拟机类加载机制
看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩 ...
随机推荐
- SPOJ - DQUERY
题目链接:传送门 题目大意:一个容量 n 的数组, m次询问,每次询问 [x,y]内不同数的个数 题目思路:主席树(注意不是权值线段树而是位置线段树) 也就是按一般线段树的逻辑来写只是用主席树实现而已 ...
- CSS 3D的应用记录
为父元素添加以下样式后,子元素即可使用3D属性,例如translateZ /*设置子元素也应用3D效果*/-webkit-transform-style: preserve-3d;-moz-trans ...
- 自行颁发不受浏览器信任的SSL证书
ssh登陆到服务器上,终端输入以下命令,使用openssl生成RSA密钥及证书. # 生成一个RSA密钥 $ openssl genrsa -des3 -out 33iq.key 1024 # 拷贝一 ...
- ios 在UIView上画图,线条
1.画线条(实线,虚线) - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext( ...
- 微信小程序 --- 事件绑定
事件类别: tap:点击事件: longtap:长按事件: touchstart:触摸开始: touchend:触摸结束: touchcansce:取消触摸: 事件绑定: bind绑定: catch绑 ...
- Python 自学积累(二)
1. onfigParser 模块用于操作配置文件 注:Parser汉译为“解析”之意. 配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数( ...
- java利用poi 把ppt转化为图片,
导入jar包: poi-3.8.jar poi-ooxml-3.9.jar poi-scratchpad-3.8.jar 代码: package test4; import java.awt.Dime ...
- CentOS 6.7 配置LVM (逻辑卷管理)
LVM 简介 LVM是逻辑盘卷组管理 (Logical Volume Manager) 的简称. LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的灵活性,在一定程度上解决普通磁盘分区带来 ...
- Python开发【Django】:CMDB基础
浅谈ITIL TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central ...
- 'ascii' codec can't decode byte 0xc4 in position 27: ordinal not in range(128)
This error happens when I try to run d:\linux\linuxkernel\android\内核\blog\BlogBackup(v1.1)source\htm ...