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

Posted 吴豪杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《深入理解Java虚拟机》学习笔记相关的知识,希望对你有一定的参考价值。

本系列文章为《深入理解Java虚拟机: JVM高级特性与最佳实践》阅读笔记。

垃圾收集器与内存分配策略

  1. 引用计数法 : 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不可能再被使用的。但是,其不能解决对象之间的相互循环引用的问题。
  2. Java和C#,甚至包括古老的Lisp,都是使用 根搜索算法 判定对象是否存活的。该算法通过一系列「GC Roots」对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到「GC Roots」没有任何引用链相连(用图论的话来说就是从「GC Roots」到这个对象不可达)时,则证明此对象是不可用的。
    在Java中,「GC Roots」包括:

    • 栈中引用的对象
    • 静态引用对象
    • 常量引用对象
    • JNI所引用的对象
  3. Java中引用分为: 强引用 (不被回收)、 软引用 (内存不足进行第二次回收)、 弱引用 (随时回收)、 虚引用 (最弱的关系,不能取得实例)。

  4. 如果覆写了 finalize() 方法且有必要,虚拟机会触发 finalize() 方法,且只会调用一次,但并不承诺会等待它运行结束。
  5. 回收常量: 判断有无对象引用常量池中的常量;
  6. 回收类: 满足下列三个条件才可以被回收。

    • 该类的所有实例都被回收
    • 加载该类的ClassLoader已经被回收
    • 该类对应Class对象没有在任何地方被引用
  7. 垃圾收集算法: 「标记清除算法」、「复制算法」、「标记整理算法」、「分代收集算法」。

  8. 垃圾收集器(7种作用于不同分代的收集器): Serial收集器(Stop the World)、ParNew收集器(多线程版Serial)、Parallel Scavenge收集器、CMS(并发收集、低停顿)、G1收集器(Java 1.7、标记整理、精准控制停顿)
  9. 内存分配策略:

    • 对象优先在Eden分配
    • 大对象直接进入老年代,如数组、字符串
    • 长期存货的对象将进入老年代,默认年龄达到15岁进入,当然并不是一定达到才可以进入
  10. 空间分配担保: 每次晋升到老年代的平均大小如果大于老年代的剩余空间大小,则进行一次「Full GC」

    Minor GC: 新生代GC;Full GC: 老年代GC

类文件结构和类加载

  1. 魔数与Class文件版本: 很多图片文件头都存有魔数,比如gif或jpeg。Class文件的魔数是0xCAFEBABE。魔数后面分别是2个字节的次版本号和2个字节的主版本号。版本号从45开始的。

  2. 版本号后面紧跟的是常量池容量计数值,从1开始计数。(P143)

  3. 类加载时会先加载父类,接口则只在用到父接口的时候才加载。
  4. 类加载过程: 加载 -> 验证 -> 准备 ->(解析)-> 初始化 -> 使用 -> 卸载

    解析在某些情况下可以在初始化阶段之后再开始

  5. static 变量在准备阶段就已经分配内存,但通常情况不会为其赋值初始化,初值为0,除非存在 final 修饰,那样便会立即初始化。对于静态变量和静态代码块,编译器先变量赋值,再静态代码块。且先执行父类,即Object中的静态代码块先于任何一个类中的变量赋值和静态代码块。
  6. 两个类相等不仅要「Class对象相等」,而且「ClassLoader也要相等」。
  7. 双亲委派模型 : 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

虚拟机字节码执行引擎

  1. 局部变量Slot回收要满足:

    • 超出作用域
    • 有新的局部变量覆盖Slot区
  2. 操作数栈 : 例如加法运算中的两个数

  3. 栈帧信息 : 一般会把动态连接(指向方法等的符号连接)、方法返回地址与其他附加信息全部归位一类,称为栈帧。
  4. 对于静态等已经确定了的方法(不会被覆写),调用时直接将符号引用转化为直接引用,这种调用方法称为解析。Java虚拟机中方法调用对应四条指令:
    • invokestatic: 调用静态方法
    • invokespecial: 调用实例构造器、私有方法和父类方法
    • invokevirtual: 调用所有的虚方法,和final修饰的方法
    • invokeinterface: 调用接口方法

待续

以上是关于《深入理解Java虚拟机》学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

听说你在学习java虚拟机,这些资源助你少走歧途!!!

《深入理解Java虚拟机-第3版》 学习笔记,一文涵盖全书精髓

深入理解 Java 虚拟机之学习笔记

深入理解java虚拟机学习笔记

深入理解Java虚拟机- 学习笔记 - 虚拟机类加载机制

深入理解 Java 虚拟机之学习笔记