《深入理解Java虚拟机》笔记

对象的内存布局

 对象的内存布局:对象头,实例数据,对齐填充。
重点分析对象头,这部分和锁相关。
对象头一般由两部分组成:Mark word和Class Meta Data Address(存储指向对象存储类型的指针)。如果对象为数组,对象头还会多出Array Length数组长度这个组成部分。
32位的Jvm对象头 Mark Word组成如下
《深入理解Java虚拟机》笔记

类加载过程

 Java虚拟机的类加载全过程分为加载、验证、准备、解析、初始化 5个阶段。

  • 加载
    在加载阶段,虚拟机要完成几件事:
     (1)通过类的全限定名来获取定义此类的二进制字节流。(二进制流的获取方式有多种,从zip,jar,war包等;从网络中获取如Applet;运行时动态生成如动态代理技术;由其他文件生成如JSP;从数据库中读取)
     (2)将这个字节流代表的静态存储结构转化为方法区的运行时数据结构。
     (3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
  • 验证
     验证确保了Class文件中的字节流包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
     验证大致会完成以下四个阶段的检验动作:
    (1)文件格式检验
     验证字节流是否符合Class文件格式规范,并且能被当前虚拟机版本处理。
    这个阶段的检验时基于二进制字节流进行的,只有通过了这个阶段的验证后,字节流才会进入内存的方法区进行存储,后面的3个检验全是基于方法区的存储结构进行的,不会再操作字节流。
    (2)元数据验证
     对类的元数据信息进行语义检验,保证不存在不符合Java语言规范的元数据信息。
    (3)字节码验证
     通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。这个阶段会对类的方法进行校验。
    (4)符号引用验证
     最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在链接的第三阶段----解析阶段发生。
  • 准备
      此阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区内分配。
  • 解析
     此阶段是虚拟机将常量池中的符号引用转变替换为直接引用的过程。
      虚拟机实现可以根据需要来判断到底是在类被加载器加载时就对常量池的符号引用进行解析,还是等到一个符号引用被使用时才去解析。
  • 初始化
     初始化阶段是执行类构造器的方法的过程

双亲委派模型

 从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器Bootstrap ClassLoader,使用C++实现,是虚拟机本身的一部分;另一种是所有的其他类加载器,由Java语言实现,独立于虚拟机外部,并且全都继承于java.lang.ClassLoader。
 从开发人员角度,类加载器分为启动类加载器Bootstrap ClassLoader,扩展类加载器 Extension ClassLoader,应用程序类加载器 Application ClassLoader。
《深入理解Java虚拟机》笔记
 双亲委派模型的工作过程是:如果一个类加载器接收到加载类的请求,首先不会自己尝试去加载这个类,总是会委派父加载器进行加载,当父加载无法加载时,子加载器才会尝试自己去加载。
 对于保证Java程序的正常运行非常重要,但实现却很简单,实现代码在java.lang.ClassLoader中的loadClass()方法中。逻辑清晰易懂:先检查这个类是否被加载过,如果没有则请求父加载器loadClass()进行加载,如果父类加载器为空则默认使用启动类加载器作为父加载器进行加载。如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。

相关文章: