JVM类的加载和初始化
2019-10-10 09:43:57 0 举报
类加载流程图
作者其他创作
大纲/内容
解析
常量(编译期):常量是编译期间存放在调用常量的方法所在类的常量池中,本质上并没有引用到定义常量的所在类。因此不会触发定义常量所在类的初始化。public static final int i=7常量(运行期)和编译期常量不同,运行期常量是在运行期间确定的,它不会放在调用该常量类的常量池中,因此会触发定义该常量类的初始化public static fina int i=new Random().nextInt(1);
加载
ClassLoader加载类
确保JVM加载字节码符合规范验证分为:文件格式验证->元数据验证->字节码验证->符号引用验证->二进制兼容性验证
为静态域分配存储空间准备阶段,Java虚拟机为类的静态变量分配内存,并设置默认的初始值。比如int的默认值是0 并分配4个字节的内存控界,引用对象的默认值是null
类的加载原理
编译
卸载
Bootstrap Loader 自动加载AppClass Loader(系统类加载器),将其父类Loader 设置为Extended Loader
编译 .java-->.class文件
原理
寻找jre目录,寻找jvm.dll,并初始化JVM
执行初始化
使用
符号引用转换成直接引用。对类的字段和方法进行转换
最后由AppClass Loader 加载HelloWorld类
准备
1,遇到new,getstatic,putstatic,invokestatic 这4条字节码指令的时候具体: 1)new 实例化一个类 2)读取/设置静态字段:不包括final修饰的字段 (这些final修饰的字段已经放入常量池中) 3)执行静态方法2,初始化一个类的子类,而他的父类没有初始化时,先初始化父类3,使用java.lang.reflect.*的方法对类进行反射调用4,Java虚拟机启动时被标明为启动类的类包含main方法的类5,JDK1.7开始提供动态语言的支持(使用Class.forName(String className) 加载类)ClassLoader的loadClss(String className)的方法只会加载并编译某类,并不会对其执行初始化
初始化就是执行类的 <clinit>(){……}方法把静态变量的赋值和静态代码块等操作顺序串连成一个方法。调用顺序的例子:父类静态块-->子类静态块-->父类构造块-->父类构造函数-->子类构造块-->子类构造函数
public class ClassInitTest { public static void main(String[] args) { System.out.println(Child.str1); } static{ System.out.println(\"main static block.......\"); }}class Parent{ static String str1 = \"hello\"; static{ System.out.println(\"parent static block.....\"); }}class Child extends Parent{ static String str2 = \"world\"; static{ System.out.println(\"child static block.......\"); }}
输出结果:main static block.......parent static block.....hello分析下:1,访问Child.str1会执行类的初始化,会执行类的静态代码块内容2,对于静态变量,只有直接定义了该变量的类才会被初始化。因此Child类不会执行初始化输出结果:
产生一个Bootstrap Loader(启动类加载器)
验证
是主动调用
JVM负责
是否属于五种主动引用
主动引用初始化类
被动引用不会初始化类
Bootstrap Loader 自动加载Extended Loader(标准拓展类加载器),并将其父Loader设置为Bootstrap Loader
链接
1,子类调用父类的静态变量,子类不会被初始化,父类会被初始化,但是不会调用构造函数2,创建类的引用数组,该类不会被初始化,eg Main[] list = new Main[10];3,调用类的final静态常量,不会初始化该类4,ClassLoader的loadClass方法只会加载类,不会初始化类
Java文件
0 条评论
下一页