虚拟机的类加载机制1 类加载的时机
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类
即虚拟机的类加载机制.
在Java中,类型的加载、链接和初始化过程都是在程序运行期间完成的
如编写一个面向接口的应用程序,可等到运行时再指定其实际的实现类. 这种策略虽然会令类加载时增加一些性能开销,但是会为Java应用程序提供高度的灵活性.
Java天生的可以动态扩展的语言特性就是依赖运行期动态加载和动态链接
1 类加载的时机
类从被加载至内存到卸载出内存的生命周期
其中加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的. 而解析阶段可能会在初始化阶段后再开始.
虽然上述的5个阶段可能按序,但是并不是说一个接一个阶段完成后才开始,一个阶段的进行完全可能激活另一个阶段的进行,交叉混合式的进行
什么情况下需要开始类加载过程的第一个阶段-加载呢? 并无强制规范,但对于初始化阶段,有且只有以下5种情况必须立即对类进行初始化
- 遇到new、getstatic(读取一个类的静态字段)、putstatic或invokestatic(设置一个类的静态字段)这4条指令的时候,如果类没有进行过初始化.则先触发其初始化
- 使用反射包方法进行反射调用的时候,如果类未经初始化,则先触发其初始化.
- 当初始化一个类的时,若其父类未经初始化,则先触发其父类的初始化.
- JVM启动时,用户需指定一个主类,虚拟机会先初始化此类
- 当使用JDK7的动态语言支持时,如果一个java.lang.invoke.MethodHandler实例最后的解析结果为REF_getStatic、REF_pusStatic、REF_invokeStatic的方法句柄(句柄中包含了对象的实例数据和类型数据,句柄是访问对象的一种方法.句柄存储在堆中),并且句柄对应的类没有被初始化,那么先触发其初始化
这5种行为称为对一个类进行主动引用
,此外的所有引用类的方式都不会触发初始化,称为 被动引用
输出结果
初始化父类!
666
- 原因分析 本示例看似满足初始化时机的第一条:当要获取某一个类的静态字段的时候若该类尚未初始化,则对该类进行初始化
但由于这个静态成员变量属于父类,子类只是间接调用父类中的静态字段,因此子类调用value属于间接引用,而父类调用value属于直接引用
对于静态字段,只有直接定义这个字段的类才会被初始化,通过其子类引用父类中定义的静态字段,只会触发父类的初始化!
并没有输出”初始化父类!”
- 原因分析 这个过程看似满足初始化时机的第一条:遇到new创建对象时若类没被初始化,则初始化该类
但现在通过new要创建的是一个数组对象,而非SuperClass类对象,因此也属于间接引用,不会初始化SuperClass类
输出结果
hello world
- 原因分析 本示例看似满足类初始化时机的第一个条件:获取一个类静态成员变量的时候若类尚未初始化则初始化类.
但ConstClass类的静态字段被final修饰,是一个常量 被final修饰的常量在Java代码编译的过程中就会被放入它被引用的class文件的常量池中(这里是NotInitialization的常量池). 所以程序在运行期间如果需要调用这个常量,直接去当前类的常量池中取,而不需要初始化这个类
实际上,NotInitialization的Class文件中并无ConstClass类的符号的入口,这俩类在编译成Class之后就不存在任何联系了
接口和类都需要初始化,接口和类的初始化过程基本一样,有所区别的是前面说的5种情景的第三条
- 类初始化时,如果发现父类未经初始化,则先初始化父类,然后再初始化自己
- 接口初始化时,并不要求父接口已经全部初始化,只有在运行过程中用到当父接口时(如引用接口中定义的常量)才初始化父接口
- [接口测试 - 基础篇] 03 unittest测试框架了解多少才够?
- 关关的刷题日记09——Leetcode 80. Remove Duplicates from Sorted Array II
- [linux][kernel]dump kmsg到文件系统中
- [接口测试 - 基础篇] 12 还是要掌握python日志管理模块的
- Spring整合Quartz分布式调度
- [接口测试 - 基础篇] 11 掌握下python解析YAML格式也是需要的
- 如何用Python创建眼下火爆的区块链?这篇干货请收藏
- [接口测试 - 基础篇] 10 别啊,还有INI格式呢,别忘记我
- [接口测试 - 基础篇] 09 其实吧,读写csv格式也是要掌握的
- 【源码分享】机器学习之Python支持向量机
- [接口测试 - 基础篇] 08 封装个基本的excel解析类
- 关关的刷题日记10——Leetcode 1. Two Sum 方法1
- BZOJ 2463: [中山市选2009]谁能赢呢?(新生必做的水题)
- 10个Python面试常问的问题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法