类初始化

1.类加载

  • 遇到new、getstaic、putstatic或invokestatic这四条字节码指令,如果类没有进行过初始化,则需要先触发其初始化。这四大场景分别是:使用new关键字实例化对象读取或者设置一个静态字段调用类的静态方法
  • 使用java.lang.reflect包的方法对类惊醒反射调用的时候。
  • 当需要初始化的类的父类没有初始化时。
  • 虚拟机启动时,用户需要指定一个要执行的主类(main),虚拟机会初始化这个类。
  • 使用动态语言时,如果一个java.lang.invoke.MethodHandle实例最后解析结果是方法句柄(详见JVM虚拟机详解)则需触发其初始化。
    (tips:对于静态字段,只会触发直接定义这个字段的类才会被初始化;接口也有初始化过程,有且只有上面的第三种情况来初始化,由编译器自动生成<clinit>类构造器,初始化接口中所定义的成员变量。同时,类初始化要求其父类全部完成初始化,但是初始化接口时,不要求其父接口全部完成初始化,只有真正用到父接口的时候(如引用接口定义的常量)才会初始化)

类的生命周期

一个非数组类的加载阶段是开发人员可控性最强的,因为除系统提供的加载器外,还可以用户自定义类加载器去控制字节流的获取方式。
(tips:加载阶段与连接阶段的部分内容是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,任然属于连接阶段,这两个阶段的开始时间仍然保持着固定的先后顺序。)
本阶段需要完成下面工作:

  • 通过一个类的全限定名来获取定义此类的二进制字节流。
  • 通过这个字节流转换为运行时数据结构。
  • 在内存中生成一个代表类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
    (tips:相对于类加载的其他阶段,此阶段可控性最强,可以用用户自定义的类加载器来实现。)

2.连接

共包含验证、准备、解析三个阶段。

2.1验证

Java虽然是相对安全的语言,但Class文件并不一定要求用Java源码编译而来,因此验证阶段就非常重要了,这个阶段的严谨,直接决定了Java虚拟机是否能承受恶意代码的攻击,验证阶段在类加载子系统中占了相当大的部分。
共四个阶段:****文件格式验证、元数据验证、字节码验证、符号引用验证****。
字节码验证是整个过程最复杂的阶段:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。在第二阶段对元数据信息中的数据类型做完校验后,这个阶段将对类的方法体进行校验分析,确保不危害虚拟机。

2.2准备

准备阶段为类变量分配内存并设置类变量初始值的阶段。这些变量所使用的内存将直接使用方法区分配。这个阶段仅实例化类变量,而不包括实例变量。实例变量将会在对象实例化随着对象一起分配在Java堆中。其次,这里所说的初始值通常情况下是指数据类型的零值,准备阶段不会执行任何用户代码。用户的赋值是在程序被编译后,存放于类构造器(<clinit>)中。如果类字段的字段属性表中存在ConstantValue,那么准备阶段就会初始化为ConstantValue的值,即final修饰的变量。

2.3解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。(符号引用就是一组符号来描述目标,可以是任何字面量。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。)

3初始化

类加载的最后一步,之前的部分,除了加载用户自定义的类加载器之外,其余动作都是由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。初始化阶段是执行<clinit>()方法的过程。

  • <clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的,静态语句块中智能访问到定义在静态语句块之前的变量,定义在其之后的便令,在前面的静态语句块可以赋值但不能访问。
  • <clinit>()与类的构造函数不同,他不需要显式地调用父类构造器,虚拟机保证在自雷<clinit>()方法之前,父类的<clinit>()方法已经执行完毕。
  • 由于父类的<clinit>()方法先执行,也就意味着父类中定义的静态语句块要优先于子类型的变量赋值操作。
  • 如果类中没有静态语句块,也没有对类变量的赋值奥做,那么编译器可以不为这个类生成<clinit>()方法。
  • 接口中不能使用静态语句块,但仍然由变量初始化的赋值擦偶哦,因此接口和类一样都会生成<clinit>()方法,执行接口的<clinit>()不需要先执行父接口的<clinit>()方法。只有负借口定义的变量使用时,父接口才会初始化,接口的实现类初始化时也一样不会执行接口的<clinit>()。
  • 虚拟机保证,会有一个类<clinit>()方法在多线程环境找那个被正确得枷锁,同步,如果多线程同时曲初始化一个类那么只有一个类会执行这个方法,其他阻塞。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容