虚拟机内存加载机制:虚拟机把描述类的数据从Class文件中加载到内存中,并对数据进行校验、转换解析和初始化,最终形成可以别虚拟机直接使用的java模型: 一个粗糙的流程图
和那些在编译时需要进行连接工作的语言不通,java的类型的加载、连接和初始化过程都是在程序的运行期间完成的,这种策略虽然会令类加载时稍微增加一些性能的开销,但是会为java应用程序提供高度的灵活性。
依赖于运行期动态加载和动态连接这个特点实现了java的动态可扩展性
类从被加载到虚拟机内存中开始,到卸载处内存为止,整个生命周期包括: 加载、验证、准备、解析、初始化、使用、卸载七个阶段。
验证、准备、解析: 这三个阶段称为连接
对于其中的加载、验证、准备、初始化、卸载:五个阶段是固定的,但解析阶段不一定:他在某些情况下可以在初始化阶段之后在开始,这是为了支持java的运行时绑定(动态绑定或者晚期绑定)
虚拟机规范要求: 有且只有下面五种情况必须进行java初始化
- 用new构建对象或者操作静态方法或者变量的时候:getstatic、putstatic、invokestatic
- 使用java.lang.reflect包中的方法对类进行反射调用的时候,如果类没有进行初始化,则需要先触发其初始化。
- 3.初始化一个类的时候,发现其父类没有初始化,则先要初始化其父类
- 4.虚拟机启动时,用户指定一个执行的主类(含有main方法的类),虚拟机会先初始化这个类
- 5.jdk1.7的动态语言支持
被动引用:
- 1.通过子类调用父类定义的静态字段,只会触发父类的初始化,而子类则不会被触发
- 通过定义数组引用类,不会触发此类的初始化
package test1;
public class Father {
public static int value = 1;
static {
System.out.println("Father............");
}
public static void main(String[] args) {
System.out.println("Sun.value: "+Sun.value);
// Father [] s = new Sun[10];
}
}
class Sun extends Father{
static {
System.out.println("Sun...........");
}
}
结果:
Father............
Sun.value: 1
类加载的过程之加载(Class loading)(重点)
- 1、通过一个类的全限定名来获取定义此类的二进制字节流
- 2 、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 3、在内存中生成一个代表这个类的java.lang.class对象,作为方法区的这个类的各种数据的访问入口