第七章 虚拟机类加载机制

类加载机制:
虚拟机把描述类的数据从Class文件加载到内存,并队数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。

类生存过程:类加载-使用-卸载
类加载过程 : 加载-连接-初始化
连接过程: 验证-准备-解析

过程说明

  • 加载
  1. 通过一个类的全限定名来获取定义此类的二进制字节流.
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构.
  3. 在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据访问入口.
  • 验证

为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全.
文件格式验证,元数据验证,字节码验证,符号引用验证.

  • 准备

正式为类变量分配内存并设置类变量(static 修饰的) 初始值,这些变量所使用的内存都将在方法区中进行分配.

class Test{
    int x ; // 对象实例化的时候会分配
    static int y =123; //准备后为0, 初始化后为123
    static final int z = 123;//准备后为123
}
  • 解析

    虚拟机将常量池内的符号引用替换为直接引用.

  • 初始化

    初始化阶段是执行类构造器<clinit>()方法的过程.

  • <clinit>()方法由编译器自动收集类中的所有类变量(static变量)的赋值动作和static语句块中的语句合并产生.

  • 虚拟机保证子类的<clinit>()执行之前父类的已经执行完毕.

  • 虚拟机会保证一个类的<clinit>()方法在多线程的环境中被正确的加锁,同步.

5种触发初始化的情况:

  • new对象,read/write static field(except final static field), invoke static method,如果发现这个类没有被加载过;
  • java.lang.reflect反射的未初始化的类
  • 初始化一个类,如果他的父类未初始化过
  • 虚拟机启动时那个带main方法的主类
  • 如果解析结果是REF_getStatic,REF_putSTatic,REF_invokeStatic,所对应的类没有初始化过

类中static初始化:
static字段和static语句块按照先后顺序被<clinit>()收集并执行。父类的优先于子类执行。

public class SubCls extends Parent {

    static String sub_y = "sub static field y";

    static {
        System.out.println("sub static block");
        sub_x = "sub static block x";
        sub_y = "sub static block y";
        // System.out.println(sub_x); can not use the field after the block
    }

    static String sub_x = "sub static field x";

    public static void main(String[] args) {
        System.out.println(sub_x); // static field x
        System.out.println(sub_y); // y - static block
    }
}
class Parent {

    static String p_x = "parent static field x";

    static {
        System.out.println("parent static block");
        p_x = "parent static block x";
    }
}
parent static block
sub static block
sub static field x
sub static block y

双亲委派模型

工作过程:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。每一个层次的类加载器都是如此。只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

好处:

Java类随着他的类加载器一起具备了一种带有优先级的层次关系。相反如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户编写了一个称为java.lang.Object的类,并防在ClassPath中,那系统中将出现多个不同的Object类。

类加载器:

  • 启动类加载器(Bootstrap ClassLoader): C++ ; <JAVA_HOME>\lib
  • 扩展类加载器(Extension ClassLoader):JAVA ;<JAVA_HOME>\lib\ext
  • 应用程序类加载器(Application ClassLoader): JAVA ; ClassPath
  • 自定义类加载器(User ClassLoader)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1概述 在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用。而虚拟机如何加载这些Clas...
    骊骅阅读 3,034评论 0 1
  • 7.1概述 虚拟机把描述类的数据从class文件加载到内存,经过校验、转换解析、初始化,最形成能够被虚拟机直接使用...
    cremin阅读 2,523评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,828评论 19 139
  • 记不清这是哪一次约后街五个人开小灶了,那个时候五个人有一种神奇的魔力就是爱吃哪家哪家店就会消失,因为我们爱吃的都是...
    Yunkilady阅读 1,774评论 0 0
  • 姓名:庹亚军 公司:宁波贞观电器有限公司 组别:第235期 利他一组 【日精进打卡第 409天】 【知~学习】 看...
    tyj小电工阅读 1,423评论 0 0

友情链接更多精彩内容