《深入理解Java虚拟机-JVM高级特性与最佳实践》学习总结(第七章)

第七章 虚拟机类加载机制

整体结构
7.1 类加载特性

与那些在编译时需要进行连接工作的语言不同,在JAVA中,类型的加载和连接过程都是在程序运行期间完成的,这样会在类加载时稍微增加一些性能开销,但是却能为JAVA应用程序提高高度的灵活性,JAVA中天生可以动态扩展的语言特性就是依赖运行期动态加载和动态连接这个特点实现的。

7.2 类加载过程
JVM类加载过程

加载(Loading)->验证(Verification)->准备(Preparation)->解析(Resolution)->初始化(Initialization)->使用(Using)->卸载(Unloading)
** 其中验证,准备,解析这三个过程称为连接 **
** 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的 **

7.3 加载(Loading)过程

加载过程以及完成之后要做的两件事情:
1.通过一个类的全限定名来获取定义此类的二进制字节流
where&how获取二进制流?

  • 从JAR、EAR、WAR格式的包中(Tomcat就是通过部署在上边的WAR包来运行整个web项目的)
  • 从网络中获取(Applet应用)
  • 动态代理技术(java.lang.reflect.Proxy)
  • JSP文件
  • 从数据库中读取(中间件服务器SAP Netweaver)

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构:即java.lang.Class对象

7.4 验证(Verification)过程

7.4.1 目的:为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。(WHY?因为Class文件不仅仅可以由java源文件编译形成,也可以人为构造Class文件。如果输入的字节流不符合Class文件的存储格式,抛错:java.lang.VerifyError)
7.4.2 四大验证步骤:

  1. 文件格式验证:(来源于HotSpot虚拟机标准)
    1.1 是否以魔数0xCAFEBABE开头
    1.2 主、次版本号是否在当前虚拟机处理范围之内
    1.3 常量池的常量中是否有不被支持的常量类型
    1.4 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量
    1.5 CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据
    1.6 Class文件中各个部分以及文件本身是否有被删除的或附加的其他信息
    1.7 more......
  2. 元数据验证
    作用:语义验证,保证不存在不符合java语言规范的元数据信息
    通常验证以下几项内容:
    2.1 这个类是否有父亲(除了java.lang.Obejct之外,所有的类都应当有父类)
    2.2 这个类的父亲是否继承了不允许被继承的类(被final修饰的类)
    2.3 如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法
    2.4 类中的字段、方法是否与父类产生了矛盾
    2.5 more......
  3. 字节码验证
    作用:对类的方法体进行校验分析,确保被校验类的方法在运行时不会做出危害虚拟机安全的行为
    3.1 保证任意时刻操作数栈的数据类型与指令代码都能配合工作,例如不会出现类似这样的情况:在操作栈中放置了一个int类型的数据,使用的时候却按long类型来加载到本地变量表中
    3.2 保证跳转指令不会跳转到方法体以外的字节码指令上
    3.3 保证方法体中的类型转换是有效的,例如可以把一个子类对象赋值给父类数据类型,这是安全的,反之则是危险的。
    3.4 more......
    ** 注意:如果一个方法体通过了字节码验证,也不能说明其一定就是安全的。(Halting Problem停机问题。) **
  4. 符号引用验证
    作用:将符号引用转化为直接引用,在"解析阶段"中发生。如无法通过验证,则抛错:IncompatibleClassChangeError异常的子类,如java.lang.IllegalAccessError、java.lang.NoSuchFieldError、java.lang.NoSuchMethodError等
    4.1 符号引用中通过字符串描述的全限定名是否能找到对应的类
    4.2 在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段
    4.3 符号引用中的类、字段和方法的访问行(private,protected,public,default)是否可被当前类访问
    4.4 more......
7.5 准备(Preparation)过程

1.作用:正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
2.为类变量分配是指:被static修饰的变量,不包括实例变量。实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
3.这里的初始化是指"通常情况"下数据类型的零值
例子:public static int value = 123;
这里的value变量,在准备阶段过后的初始值为0,而不是123,因为这时候尚未开始执行任何JAVA方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器<clinit>()方法之中,所以value = 123的动作将在初始化阶段才会被执行
4.除了上边提到的数据初始化的"通常情况",还有"特殊情况":
public static final int value = 123;
这个时候类字段的字段属性就有了ConstantValue属性,那在准备阶段变量value就会被初始化为ConstantValue属性所指定的值

数据类型 零值
int 0
long 0L
short (short)0
char '\u0000'
byte (byte)0
boolean false
float 0.0f
double 0.0d
reference null
7.6 解析(Resolution)过程

作用:虚拟机将常量池内的符号引用替换为直接引用的过程。
** 那么,什么是符号引用和直接引用呢? **

  • 符号引用(Symbolic References):符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。
  • 直接引用(Direct References):直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经在内存中存在。

** 那么,什么时候解析呢?**
虚拟机规范并未规定解析阶段发生的具体时间,只要求了在执行anewarray、checkcast、getfield、getstatic、instanceof、invokeinterface、invokespecial、invokestatic、invokevirtual、multianewarray、new、putfield、putstatic这13个用于操作符号引用的字节码指令之前。
** 针对的对象是什么呢? **
解析动作主要针对类或接口、字段、类方法、接口方法四类符号引用进行,分别对应于常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info四种常量类型

7.7 初始化(Initialization)过程

该过程是类加载过程的最后一步。在该过程中,才开始真正执行类中定义的Java代码。(注意该过程并不是对象的实例化

虚拟机会执行类构造器<clinit>()方法来初始化该类。简单归纳一下就是:

  • 类的初始化:(最后一步)执行面向类的构造器(<clinit>())
  • 对象的初始化:执行面向对象的构造器(Constructor)

回归正题:
类构造器<clinit>()方法是指:该方法是由编译器自动收集类中的所有类变量赋值动作静态语句块中语句合并产生的。编译器收集的顺序是由语句在源文件中出现的顺序决定的。
注意:静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块中可以赋值,但是不能访问

更多详细的细节见《深入理解Java虚拟机》7.3.5章节

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容