美文网首页
深入理解JVM阅读笔记

深入理解JVM阅读笔记

作者: pepsi1000 | 来源:发表于2019-08-09 11:15 被阅读0次

    1. JVM运行时数据区

    除了方法区和堆属于线程共享,其它属于线程私有。

    1.1. 程序计数器

    Java文件经过javac编译成字节码文件后,通过字节码解释器执行字节码指令时,存在线程上下文切换。程序计数器用于记录字节指令的行号,这样线程上下文切换之后,字节码解释器才会记得上一个线程执行到哪个位置。

    1.2. 虚拟机栈

    • Java方法
    • 递归调用方法存在StackoverflowError
    • 操作数栈,动态链接
    • 疑问:频繁出栈和入栈是否会影响应用性能?

    1.3. 本地方法栈

    非Java方法

    举例:CAS是一条CPU原子指令,类似数据库乐观锁的作用,JUC。

    1.4. 方法区

    存储类信息,常量(常量池,hashSet实现不允许重复),静态变量等。

    存在OM

    1.5. 堆

    1)负责数组和实例对象创建和存储(分配内存)。

    2)存在OM

    3)堆结构:

    • 新生代
      • Eden 8
      • Survivor 2
        • Survivor From 1
        • Survivor To 1
    • 老年代

    4)-Xmx -Xms

    5)HotSpot 使用永久代实现方法区,目的是想让GC管理这块内存。

    6)即便JVM提供自动分配和释放内存,程序依然存在内存泄漏内存溢出的问题。

    2. 对象创建流程

    2.1. 检查

    • 若常量池中存在类符号引用,则类已加载,直接分配内存

    2.2. 加载

    2.3. 分配内存

    • 指针碰撞
    • 空闲列表 CAS

    2.4. 初始化

    2.5. 执行<init>

    • static代码块

    3. Java对象内存布局

    3.1. 对象头

    3.2. 实例数据

    3.3. 对齐填充

    4. 如何访问对象

    4.1. 直接指针访问

    • 访问效率高,不方便GC回收

    4.2. 对象句柄访问

    • 方便GC回收,访问效率低

    5. GC回收如何对象?

    1. 配置虚拟机启动参数。配置参数之后,程序运行期间,若发生GC,就会打印GC日志详情。
    vm options: -verbose:gc -XX+PrintGcDetails
    
    1. 在程序中通过调用静态方法,触发GC
    System.gc();
    

    5.1. 引用计数法

    • 优点是简单方便,缺点是无法检测循环引用。

    5.2. 可达性分析法

    • GCRoute,引用链
    • HotSpot 采用这种方式。

    6. 垃圾回收算法

    6.1. 标记清除算法

    • 被标记的垃圾:不存在引用链
    • 存在问题:1)清除之后的内存是不连续的。2)标记和清除效率低。

    6.2. 复制算法

    • 两大内存区域(Eden、Survivor),搬运
    • 主要负责回收新生代对象。这是因为新生代区域内大部分对象是会被回收的,只有少部分对象需要被保留,被保留到Survivor中。
    • Survivor To 用来保存 Eden 和 Survivor From 存活的对象,然后再转移到 Survivor From ,等待第二次回收。
    • 若Survivor To 空间不足时,采取分配担保,将对象转移到老年代。

    6.3. 标记-整理算法

    • 覆盖,然后清除垃圾???
    • 适用于老年代

    6.4. 分代收集算法

    • 新生代使用复制算法,老年代使用标记-整理算法或标记清除算法

    7. 垃圾回收器

    7.1. Serial

    • 用户线程,GC线程
    • stop the work
    • 单线程,垃圾回收时,必须暂停其它工作线程,直到垃圾回收结束。
    • 客户端
    • 适用于桌面端应用。因为桌面端应用内存小,回收时间比较短,只要不太频繁就可以接受。

    7.2. ParNew

    • Serial 多线程版本
    • stop the work
    • 服务器端
    • 使用-XX:ParallelGCThreads参数限制垃圾收集的线程数,对应CPU核数。线程数太多导致频繁的上下文切换,浪费资源。
    • 并行和并发
    • 适用于新生代
    • 多线程操作存在上下文切换问题。若电脑是单核CPU,那么使用Serial效率更高,若电脑是多核CPU,那么建议使用 ParNew并行处理,要注意限制垃圾收集的线程数,尽量避免不必要的上下文切换。

    7.3. Parallel Scavenge

    • 新生代收集器 复制算法
    • stop the work
    • 并行多线程垃圾回收器(与ParNew一样)
    • 吞吐量优先
    • 设置GC停顿时间,较小会发生频繁GC
    • 设置吞吐量 99%,用户线程占99%,合适时性能最优

    7.4. Serial old

    • 单线程
    • 老年代
    • 标记-整理算法
    • Serial 使用复制算法,Serial old 使用标记-整理算法

    7.5. Parallel old

    • 多线程,并行
    • 老年代
    • 标记-整理算法
    • Parallel Scavenge 使用复制算法,Parallel old 使用标记-整理算法

    7.6. CMS

    • 并发标记和并发清除能够与用户线程一起执行。
    • 初始标记和重新标记 stop the work
    • 最短回收停顿时间
    • BS架构常用这种方式。
    • 单核CPU没有优势
    • 标记清除算法存在内存碎片

    7.7. G1

    相关文章

      网友评论

          本文标题:深入理解JVM阅读笔记

          本文链接:https://www.haomeiwen.com/subject/lnpcjctx.html