专栏首页JavaEdge虚拟机的类加载机制1 类加载的时机

虚拟机的类加载机制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种情景的第三条

  • 类初始化时,如果发现父类未经初始化,则先初始化父类,然后再初始化自己
  • 接口初始化时,并不要求父接口已经全部初始化,只有在运行过程中用到当父接口时(如引用接口中定义的常量)才初始化父接口

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java编程思想第五版精粹(五)-初始化和清理(下)

    以编译时错误的方式呈现。编译器可以为 i 赋一个默认值,但是未初始化的局部变量更可能是程序员的疏忽,所以强制程序员提供一个初始值,往往能帮助找出程序里的 bug...

    JavaEdge
  • 面试官问Java中init和clinit区别,这么回答offer应该稳了

    准备阶段,变量已经赋过一次系统要求的初始值 在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段...

    JavaEdge
  • 从JVM 源码看init和clinit到底什么区别

    准备阶段,变量已经赋过一次系统要求的初始值 在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是...

    JavaEdge
  • 神经网络到底该如何初始化?吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    abs_zero
  • 一文读懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    数据派THU
  • 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    磐创AI
  • 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    新智元
  • 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    初始化会对深度神经网络模型的训练时间和收敛性产生重大影响。简单的初始化方法可以加速训练,但使用这些方法需要注意小心常见的陷阱。本文将解释如何有效地对神经网络参数...

    小小詹同学
  • Java的初始化块及执行过程详解

    针对上面的问题,想必大家脑海中首先浮现出的答案是构造器,没错,构造器是Java中常用的对象初始化方式。

    硕人其颀
  • 深度学习基础知识(一)--- 权重初始化 --- 概念

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    TeeyoHuang

扫码关注云+社区

领取腾讯云代金券