JVM类的加载和对象实例的创建

1.类的生命周期

1.1-类的加载过程

  • 装载
    在装载阶段,java虚拟机将物理磁盘上的.class文件加载到虚拟机内存中
    • 堆中
      在堆中创建class对象对应的实例,堆中分配该class文件的内存空间(不是对象实例的空间而是代表这个类的class实例空间)
    • 方法区中
      方法区中保存该类对应的二进制数据结构,JVM将类加载到方法区中,提取类型信息,保存对应的类数据结构
    • 栈中
      栈中保存对堆中该class的引用
  • 链接
    • 验证
      验证字节码文件中的符号引用是否合理
    • 准备
      验证通过后则进行准备阶段,在这个阶段会为类的静态变量赋初始值,如int类型赋值0。特例:如果是全局常量即static final修饰的属性,在准备阶段就会显式赋值(如果赋值依赖于方法体或构造方法的执行的情况除外)。
    • 解析
      准备就绪后,解析class文件的符号引用,将符号引用替换为直接引用
      符号引用和直接引用的区别:符号引用和实际内存地址无关,其是字节码文件中表明引用的符号,直接引用反应实际的内存地址
  • 初始化
    如果在类定义时有为变量赋值,则在初始化阶段会为变量显示赋值。
    i.对于非static修饰的变量,使用init方法进行显式赋值
    ii.对于static修饰的类变量,使用clinit进行显式赋值

    iii.static常量的赋值也可能使用clinit方法,只要赋值过程设计方法或构造器的使用在这里插入图片描述

1.2-类的使用

类的使用分为两种情况

  • 主动使用
    在主动使用时,如通过new方法创建类的实例,明确使用了该类的静态变量,静态方法,通过反射获取该类对象,初始化该类的子类等,会触发该类的初始化
  • 被动使用
    在被动使用时,不一定会触发类的初始化,如明确使用的是父类的静态变量,则此时子类会被虚拟机加载但不会初始化

1.3-类的卸载

类的卸载依赖JVM的垃圾回收机制,当代表类的Class对象不在被引用时,即不可触及时,Class对象就会结束生命周期,类在方法区内的数据也会被卸载。由Java虚拟机自带的类加载器所加载的类不会被卸载,因为Java虚拟机本身会始终引用这些类加载器。

2.类的加载器

2.1-加载器分类

  • Bootstrap ClassLoader
    启动类加载器,由C/C++编写,用于加载jre/lib目录下的类
  • Extension ClassLoader
    扩展类加载器,用于加载jre/ext目录下的类
  • Application ClassLoader
    应用程序类加载器,主要用户加载用户自定义的类(用户自定义类加载器的情况除外)

2.2-基本特征

  • 可见性
    子类加载器可以访问父加载器加载的类,反之不成立。这是为了防止核心类被重复加载
  • 单一性
    对于任意一个类,都由这个类本身和加载这个类的类加载器共同确定这个类的唯一性。对于同一个类可以自定义多个类加载器加载多次

3.相关机制

3.1-双亲委派机制

向上申请,向下委托。
对于任意一个类的加载,严格遵循双亲委派机制,即由下层的应用加载器开始向上申请加载,如果上层的类加载器无法识别这个类或者没有办法加载这个类,则向下委托到能加载这个类的最高层加载器负责加载。这样做是为了防止用户篡改系统级别的类,如一个用户自定义了一个String类,则双亲委派机制能保证加载的String类一定是jre中确定的String类,自定义的String无法编译运行。

3.2-沙箱安全机制

沙箱是一个限制程序运行的环境。通过沙箱严格限制代码对本地系统资源访问,隔离代码和系统的运行环境。沙箱主要限制系统资源访问,系统资源如CPU、内存、文件系统、网络等。

4.对象实例化

  • 判断方法区中有没有该类对应的数据结构
    判断该类是否已经被加载,如果有继续执行对象实例化进程,如果没有则触发类的加载
  • 为对象分配内存空间
    在堆中为对象实例分配内存,用于存放对象实例
  • 初始化分配的空间,赋初始值
    为新建的对象属性赋初始值,String属性赋值null,int类型赋值0等
    • 指针碰撞
      维护一个指针介于已分配内存和未分配内存之间,每次分配内存后更新指针位置,可以做到分配的内存连续,防止内存碎片化。
      对应GC的标记整理算法
    • 空闲列表
      使用一个列表记录未分配的内存地址,每次分配内存挑选一片空的内存空间,容易造成内存碎片化
      对应GC的标记清除算法
  • 设置对象头
    设置该对象的身份标识,表示对象的“年龄”等信息
  • 执行init方法,赋真实值
    执行Java程序编译之后在字节码文件中生成的init()方法(称之为实例构造器),init()方法由非静态变量、非静态代码块以及对应的构造器组成,有几个构造方法就会生成几个init方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值