JVM 学习笔记 一 JVM 内存结构 垃圾回收

JVM 学习笔记 一

  • JVM 内存结构
    • StringTable 串池
    • 直接内存
  • 垃圾回收
    • 如何判断对象是否应该被垃圾回收
    • 五种引用
    • 垃圾回收算法
    • 垃圾回收器

JVM 内存结构

  1. 线程独占的
    (1)程序计数器 PC
    (2)虚拟机栈:线程运行需要的内存空间,其中是一个一个栈帧。栈帧是每个方法运行时需要的内存,当前正在执行的方法对应的栈帧叫做活动栈帧。
    (3)本地方法栈:调用到本地方法时对应的内存空间。
  2. 线程共享的
    (1)堆:主要存放 new 出来的对象。
    (2)方法区:一种规范,逻辑上属于堆内存,但也可以不在其中。1.6实现为永久代;1.8 实现为元空间,使用系统内存。

StringTable 串池

  1. 位置:1.6 在永久代的常量池中(回收效率低),1.8在堆内存中
  2. 原理:底层通过哈希表实现,避免对相同对象的重复创建
  3. 字符串变量之间的拼接原理时 StringBuilder(1.8),通过 new 的方式在堆中创建对象
  4. 字符串常量之间的拼接在编译期间优化,对象在串池中
  5. 可以使用 String 的 intern() 方法,将不在串池中的对象放入串池。
    (1)1.8 中,如果串池中没有此对象,则将该对象放入串池,如果有则不放入,并返回串池中的对象。
    (2)1.6 中,如果串池中没有此对象,则会创建一个副本放入串池,如果有则不创建,并返回串池中的对象。

直接内存

  1. 特点
    (1)常见于 NIO 操作时,用于数据缓冲区
    (2)分配回收成本较高,但读写性能高
    (3)不受 JVM 内存回收管理

  2. 分配和回收原理
    (1)使用 Unsafe 类对其进行分配和回收,回收需要手动调用 freeMemory方法
    (2)ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存

垃圾回收

如何判断对象是否应该被垃圾回收

  1. 引用计数法:当对象被引用的个数为 0 时,才被判定应该被回收。缺点:循环引用无法回收。
  2. 可达性分析(JVM 采用):判断是否可从 GCROOT 达到该对象
  3. 哪些对象可以作为 GCROOT ?
    (1)System Class 系统核心类
    (2)Native Stack 本地方法栈中的类
    (3)Busy Moniter 锁对象
    (4)Thread 中用到的对象

五种引用

  1. 强引用:由 GCROOT 直接或间接引用
  2. 软引用:发生 GC 之后仍然内存不足,就会释放软引用的对象。(可以关联引用队列)
  3. 弱引用:只要发生 GC,就会回收弱引用指向的对象。(可以关联引用队列)
  4. 虚引用:主要配合 ByteBuffer 用于释放直接内存。(必须关联引用队列)
  5. 终结器引用:用于释放对象,调用 finalize 方法。(必须关联引用队列)

当引用关联了引用队列后,一旦所引用的对象被回收,自己也会进入索引队列,等待被回收。

垃圾回收算法

  1. 标记清除:优点:快,不用真正删,只需将需要删除的区域设为空闲。缺点:会产生内存碎片
  2. 标记整理:优点:无碎片。 缺点:慢,因为需要移动。
  3. 复制算法:优点:快,没有碎片。缺点:需要占用双倍空间。
  4. 分代算法:将堆内存区域划分为新生代和老年代,新声代又划分为伊甸园和幸存区,进行分代回收。

垃圾回收器

  1. 串行:单线程工作,工作时需要 STW
    (1)Serial:工作在新生代,使用复制算法
    (2)SerialOld:工作在老年代,使用标记整理算法

  2. 吞吐量优先:多线程工作,工作时需要 STW,在垃圾回收时占用全部 cpu
    (1)ParallelGC:工作在新生代,使用复制算法
    (2)ParallelOldGC:工作在老年代,使用标记整理算法

  3. 响应时间优先:ConncurrentMarkSweep,简称 CMS ,并发标记清理,分为以下四个个阶段。工作在老年代
    (1)初始标记:会 STW,只标记和 GCROOT 直接相连的对象,耗时很短
    (2)并发标记:与用户线程一起执行,标记其他可达对象
    (3)重新标记:会 STW,在并发标记的过程中,用户线程可能会改遍一些引用,所以需要重新标记。
    (4)并发清理:与用户线程一起执行,使用标记清除算法
    CMS 的缺点:
    (1)由于使用的是标记清除算法,会产生内存碎片。
    (2)在并发清理的过程中,用户线程又会产生新的垃圾,这些垃圾无法在此次垃圾回收过程中被回收,只能等待下一次,这些垃圾又被称作浮动垃圾,所以 CMS 不能等到内存不足时在执行垃圾回收,一般当内存占比超过一定阈值时就触发垃圾回收。
    (3)当碎片过多或浮动垃圾过多导致内存不足,会导致并发失败,此时会将垃圾回收器退化为串行回收器,导致响应时间急剧上升。

  4. G1(Garbage First)

你可能感兴趣的:(java,java,开发语言,后端,jvm)