Java类加载机制-笔记2(类加载的过程)

1.类加载的目的:

一份被javac编译过的class文本文件通过加载,生成某种形式的Class数据结构进入内存, 程序可以调用这个数据结构来构造出object,这个过程是在运行时进行的,也是java动态拓展性的根基。

一个类的生命周期:

  1. javac 编译
  2. 加载
  3. 链接
  4. 初始化
  5. 使用
  6. 卸载

类加载包含了三个阶段

  1. 加载
  2. 链接
  3. 初始化

链接包含三个步骤:

  • 验证
  • 准备
  • 解析

其中,解析步骤是灵活的,他可以在初始化之前或者之后再进行,实现所谓的‘后期绑定’,其他环节则是不可改变的。

2.类加载的阶段

加载
加载是一个读取Class文件,将其转化为某种静态数据结构存储在方法区内,并在堆中生成一个便于用户调用的java.lang.Class类型的对象的过程。

注意:
这里的Class文件不仅仅是指的本地文件,泛指各种来源的二进制流,比如从网络、数据库、即时计算出来的class文件,比如著名的就是 动态代理技术,就是使用到了即时计算出来的class,然后实例化代理对象,可以自由选择二进制流。

链接
  • 验证

验证动作是有很多个步骤的,包括:文件格式验证、元数据字节码验证、符号引用验证。
文件格式验证:其实是发生在加载阶段的,如果通过,那么才能顺利加载,顺利加载后此时方法区内虽然已经存在了该class的静态结构,堆中也存在了该class类型的对象,但是这并不代表着JVM已经完全认可了这个类。如果程序想要使用这个类那么就必须进行链接,而链接的第一步就是进一步对这个类进行验证,到底对方法区内的class静态结构进行了哪些方面的验证。

元数据的验证、字节码的验证:就是对class的静态结构进行语法和语义上的分析,保证其不会产生危害虚拟机的行为。这两个步骤验证通过,那么虚拟机会姑且认为该class是安全的,但是这并不意味着验证已经完全结束了,还有一道对符号引用进行验证的步骤。
符号引用验证:它是在解析阶段内发生的,而解析阶段我们之前也提到过,它可以在初始化阶段之前或者之后进行。
验证其实包含了很多的步骤,分散在各个不同的阶段内,验证的内容是会不断发展的,除了这里提到的文本格式验证、元数据字节码验证、符号引用验证 四个环节 从低版本的虚拟机到现在 验证步骤其实已经不断的加入了各种机制。在未来,虚拟机的开发人员可能会引入更多更完善更完美的策略。

  • 准备

在元数据、字节码验证通过之后,虚拟机会姑且认为该class是安全的,这时候会进入准备阶段,准备阶段做的处理,并不复杂,就是为该类型中定义的静态变量赋0值,注意,这里仅仅是静态变量而不是成员变量,此时将会出现一个被太多人混淆和误解的概念,我们这里就好好捋一捋。
虚拟机内存规范中的定义了方法区这种抽象概念,HotSpot这种主流虚拟机在JDK8之前使用了永久代这种具体的实现方式来实现方法区。在JDK8之后,弃用‘永久代’这种实现方式,采用元空间这种直接内存取代。
在JDK8之前,类的元信息、常量池、静态变量等都存储在 永久代这种具体实现中,而在JDK8及之后,常量池、静态变量被移除‘方法区’,转移到了堆中,元信息这些呢,依然保留在方法区内,但是具体的存储方式改成了元空间。

  • 解析

该阶段主要做的事情是将 符号引用 替换为 直接引用。什么是符号引用,什么是直接引用?
当一个Java类被编译成Class之后,假如这个类称为A,并且A中 引用了B,那么在编译阶段,A是不知道B有没有被编译的,而且此时B也一定没有被加载,所以A肯定不知道B的实际地址,那么A怎么才能找到B呢?,此时在A的class文件中,将使用一个字符串S来代表B的地址,S就被称为符号引用,在运行时呢,如果A发生了类加载,到了解析阶段会发现B还未被加载,那么将会触发B的类加载,将B加载到虚拟机中,此时A中的B的符号引用将会被替换成B的实际地址,这被称为直接引用,这样也就能够真正的调用B了。
Java通过后期绑定的方式来实现多态,那么后期绑定这个概念,又是如何实现的呢?
其实就是这里的动态解析,如果A调用的B是一个具体的实现类,那么就称为静态解析,因为解释的目标类型很明确,而假如上层Java代码使用了多态,这里的B是一个抽象类或者是接口,那么 B可能有两个具体的实现类C和D 此时,B的具体实现并不明确,当然也就不知道使用哪个具体类的直接引用来进行替换,既然不知道,那么就等一等吧,直到运行过程中发生了调用,此时虚拟机调用栈中将会得到具体的类型信息,这时候再进行解析,就能用明确的直接引用来替换符号引用,这就解释了为什么解析阶段有时候会发生在初始化阶段之后,这就是动态解析,用它来实现了后期绑定。底层对应了invokedynamic这条字节码指令。

扩展:多态

扩展:动态绑定

初始化

初始化阶段简单概括:此时会判断代码中是否存在主动的资源初始化操作,如果有的话,那么执行。这里所说的主动的资源初始化动作,不是指的构造函数,而是class层面的,比如说成员变量的赋值动作,静态变量的赋值动作,以及静态代码块的逻辑。而只有显式的调用new指令 才会调用构造函数进行对象的实例化,这是对象层面的,二者不能进行混淆。

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

推荐阅读更多精彩内容