类加载

类的生命周期

类加载时机

虚拟机规范中没有规定类加载的时机,但是规定了需要进行初始化的5种情况(而加载、验证、准备必须在此之前)。

  1. 遇到new、getstatic、putstatic、invokestatic这四条字节码指令时,也就是new一个对象或者读写一个类的字段或者调用一个类的方法。
  2. 通过反射调用一个类的时候。
  3. 初始化一个类是,如果父类还没有初始化,那么先初始化父类。
  4. 虚拟机启动时,指定的含main()的主类。
  5. JDK1.7的动态语言支持,MethodHandle是一个类字段或者方法的句柄,如果这个类没有初始化,那么初始化。

不会初始化的情况:

  1. 子类引用父类的静态字段和方法,子类不会初始化。
  2. 通过数组定义引用类,类不会初始化。
  3. 引用可以在编译期确定的常量类字段,不会引起类初始化,因为这个常量已经被使用的类放入自身的常量池。
  4. 一个接口初始化时不要求父接口完成初始化,只有在真正使用父接口时才需要初始化。

类加载的过程

指生命周期中的加载、验证、准备、解析和初始化

加载

  1. 虚拟机根据类的全限定名获取类的二进制字节流。
  2. 将字节流代表的静态存储结构转化为方法区的运行时数据结构。
  3. 内存中生成一个java.lang.Class对象,作为方法区这个类的数据的入口。
获取:
  1. ZIP(jar, war, ear...)
  2. 网络(applet)
  3. 运行时生成,Proxy动态代理
  4. 其他文件生成,JSP文件生成
  5. 数据库

加载类的阶段可以通过自定义类加载器来自定义,通过重写loadClass()方法来控制获取字节流。
但是数组类稍有特殊,例如数组类C:
(1)如果组件类型为引用类型,那么递归地加载这个组件类型,然后数组C将在加载了该组件类型的类加载器的类命名空间上被标识。
(2)如果组件类型不是引用类型,那么数组C会被标记为与引导类加载器关联
(3)数组类的可见性和组件类型一致

存储:

(1)二进制流以虚拟机所需格式存储在方法区,格式由虚拟机实现自定。
(2)实例化一个java.lang.Class类的对象,HotSpot将这个对象放在了方法区。

验证

验证字节流的信息符合虚拟机要求,并且不会危害虚拟机的安全。
字节码层面来说,字节码可以完成很多Java语言无法完成的操作,而字节码可以使用很多方式生成,不一定由Java源码编译而来,所以虚拟机为了保证自身安全,需要进行验证。

  1. 文件格式验证
  • 魔数
  • 主次版本号是否支持
  • 常量池中的常量类型
  • 指向常量的索引值指向是否有问题
  • 常量池UTF8类型常量的UTF8编码
  • Class文件是否有被删除或者附加的其他信息
    ......
    这一阶段的验证是基于字节流的,通过后,字节流才会进入方法区,后面的验证会基于方法区内的存储结构,而不再操作字节流。
  1. 元数据验证
    进行语义分析,以保证满足Java语言规范
  • 除了Object外应该有父类
  • 是否继承了final类
  • 如果不是抽象类,是否实现了所有需要实现的方法。
  • 字段与方法是否与父类矛盾(覆盖了父类final字段,不符合规则的重载)
    ......
  1. 字节码验证
    通过数据流与控制流分析,确定程序语义是合法符合逻辑的。
  • 保证操作数栈的数据类型与字节码指令能配合
  • 跳转指令不会跳转到方法体之外的字节码指令
  • 类型转换是有效的
    ......
    方法体的Code属性的属性表中在JDK1.6后添加了StackMapTable,用于描述方法的所有基本块开始时本地变量表和操作栈应有的状态,验证期间,不需要在根据程序推导这些状态的合法性,只需要检查StackMapTable属性中的记录是否合法即可,这样将类型推导转变为类型检查。
  1. 符号引用验证
    这个验证发生在解析阶段虚拟机将符号引用转化为直接引用的时候,对类自身以外的信息进行匹配性校验:
  • 字符串描述的全限定名能否找到对应的类
  • 指定类中是否存在符合方法描述符所描述的方法,是否存在简单名称所描述的字段
  • 符号引用中的类、字段、方法的访问性是否可被当前类访问

准备

为类变量在方法区中分配内存,并设零值(零值而非初始值),赋初始值的指令在<clinit>()方法中,在初始化阶段执行。
但如果是final变量,字段属性表中包括ConstantValue的属性,那么会设为ConstantValue的值。

解析

将常量池中的符号引用替换为直接引用,包括常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等
详见《深入理解虚拟机》P221

初始化

执行<clinit>()方法

  • <clinit>()方法内容来自于类变量的复制动作和static块,按声明顺序
  • <clinit>()方法与构造函数不同,不需要显示调用父类构造器,虚拟机保证父类的<clinit>()方法已经执行
  • <clinit>()不是必须的
  • 接口没有初始化块,但是可以有赋值
  • 虚拟机保证一个类的<clinit>()方法在多线程环境下能被正确地加锁同步,如果多线程同时去初始化一个类,那么只有一个线程会执行类的<clinit>()方法,其他线程会阻塞。同一个类加载器下,一个类只会初始化一次。

类加载器

主要是加载阶段的“通过一个类的全限定名获取此类的二进制字节流”
用于类层次划分,OSGi,热部署,代码加密等领域

类与类加载器

任意一个类都要由加载它的类加载器和类本身一同确立它在Java虚拟机中的唯一性,也就是每个类加载器都有自己独立的类名称空间。

双亲委派模型
  • 启动类加载器(Bootstrap ClassLoader):
    <JAVA_HOME>\lib和-Xbootclasspath
  • 扩展类加载器(Extension ClassLoader):
    <JAVA_HOME>\lib\ext或者java.ext.dirs系统变量指定的类库
  • 应用程序加载器(Application ClassLoader):
    ClassPath
  • 自定义类加载器:
    父类加载器为应用程序加载器,通过组合实现

好处:
Java类随着类加载器有了层级关系

摘抄自《深入理解Java虚拟机》

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

推荐阅读更多精彩内容