生命不息,学习不止,对一切都要维持敬畏之心。
若有不正之处,请谅解和批评指正,不胜感激。

1.类加载

1.1 时机

  • new关键字
  • 读取或设置static字段
  • 调用static方法
  • 反射
  • 初始化类过程中发现其父类没有被初始化
  • 1.8版本接口中的default方法,其实现类初始化之前,要初始化接口类

1.2 过程

图片说明

  • 加载:二进制流读入内存
  • 验证:确保字节流中的信息符合<JAVA虚拟机规范>
  • 准备:静态变量,分配内存,初始化
  • 解析:虚拟机常量池中符号引用替换为直接引用
  • 初始化:根据代码指定的主观计划,去初始化资源(如变量)

1.3 类加载器

  • java.lang.ClassLoader是所有类加载器的父类
  • 引导类加载器Bootstrap
  • 扩展类加载器ExtClassLoader
  • 应用类加载器AppClassLoader
  • 双亲委派机制:当AppClassLoader收到一个加载类的请求时,会先让他的父类加载器ExtClassLoader尝试加载,ExtClassLoader也会让他的父类加载器Bootstrap尝试加载,如果Bootstrap能加载,就加载该类。如果Bootstrap不能加载,则ExtClassLoader会进行加载,如果也不能加载,AppClassLoader会进行加载。这样可以很好的避免核心类被篡改,保证了java运行的稳定性.
  • 当一个类的class文件被类加载器加载到内存后,类的加载器会创建出此class文件的对象。class文件的对象是Class类的对象

2.对象的创建流程

  • 虚拟机遇到new指令时,检查这个对应的类能否在常量池中定位到一个类的符号引用
  • 判断这个是否已被加载,验证,准备,解析和初始化
  • 在堆中为对象分配空间
    • 指针碰撞:堆的内存分配规律,一边占用另一边空闲,中间为指针,挪动对象大小的空间赋予对象.
    • 空闲列表:堆的内存分配不规律,已被使用的内存和空闲内存交错,虚拟机维护一个列表
    • 按照垃圾回收算法决定使用哪一种对象分配空间
    • 指针碰撞效率较高
  • 初始化内存空间为零
  • 设置对象头信息
    • Mark Word(hash值,锁信息等)和类型指针(指向类)
    • 实例数据(字段等)
    • 对齐填充(8的倍数)
      图片说明
  • 执行init方法

3.对象定位

  • 句柄访问
    图片说明

  • 指针访问
    图片说明

  • 对比

    • 垃圾回收:句柄访问不需要更改对象地址,指针访问需要
    • 访问效率:HoSpot采用指针访问,访问高校,不需要到句柄池拿取指针