深入理解Java虚拟机整理

JVM虚拟机

内存模型

程序计数器

  • 存储执行字节码的地址

  • JVM栈

  • 本地方法栈

    • -Xss2m

      • 栈内存

  • 回收机制

    • 新生代

      • Eden

        • 无多余空间时出发Minor GC
      • Survivor

      • -Xmn10M

        • 新生代内存10M
      • -XX:SurvivorRatio=8

        • Eden和Survivor的空间比例是8:1
      • minor gc

    • 老年代

      • major gc
      • full gc
  • 堆内

    • -Xms10m

      • 初始化堆内存
    • -Xmx20m

      • 最大堆内存
    • -XX:+HeapDumpOnOutOfMemoryError

      • 保存堆内存信息
  • 堆外(直接内存)

    • 不受JVM限制

    • -XX:MaxDirectMemorySize=10m

      • 最大直接内存

方法区

  • 存储类信息、常量、静态变量

  • -XX:PermSize=10m

    • 方法区内存
  • -XX:MaxPermSize=20m

    • 最大方法区内存
  • -verbose:gc

    • 输出gc日志
  • -verbose:class

  • -XX:+TraceClassLoading

  • -XX:+TraceClassUnLoading

垃圾收集(Grabage Collection)

存活判定算法

  • 引用计数法

    • 相互引用无法回收
  • 可达性分析法

    • GC Roots
  • 引用

    • 强引用

      • 明确赋值引用
    • 软引用

      • 在无足够内存时回收
    • 若引用

      • 下一次gc时回收
    • 虚引用(幽灵/幻影)

      • 回收时收到系统通知(finalize)

收集算法

  • 标记-清除

    • 标记垃圾并清除
    • 效率不高
    • 容易产生空间碎片
  • 复制

    • 把存活对象复制到另一块相同大小的区域,回收原区域后再把数据复制回原区域
    • 代价太高,内存利用率只有一半,一般可以分配8:1:1比例
    • 适合新生代回收
  • 标记-整理

    • 移动存活对象到一端,然后直接清理末尾端意外端内存
    • 适合老年代回收
  • 分代收集

    • 根据对象生存周期分为多个代,各个代应用不同的算法

    • 新生代

      • 复制算法
    • 老年代

      • 标记整理算法

垃圾收集启动时间

  • 到达safepoint
  • 线程在安全区域

垃圾收集器

  • Serial

    • 新生代单线程收集

    • 复制算法

    • client模式下默认的新生代收集器

      • 新生代内存一般配置的不大
    • 可以和CMS配合工作

  • ParNew

    • 新生代多线程收集
    • 复制算法
    • server模式下首选的新生代收集器
    • 可以和CMS配合工作
    • -XX:UseParNewGC
  • Parallel Scavenge

    • 新生代多线程收集

    • 复制算法

    • 可控的吞吐量(吞吐量优先)

      • 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
      • 适合交互类程序
      • 频繁收集(停顿时间过小)会造成吞吐量下降
    • -XX:MaxGCPauseMillis

      • 最大垃圾收集停顿时间(单位毫秒)
    • -XX:GCTimeRatio

      • 吞吐量大小
    • -XX:UseAdaptiveSizePolicy

      • 动态调整该收集器的参数
  • Serial Old(MSC)

    • 老年代单线程收集
    • 标记-整理算法
    • client模式下收集器
  • Parallel Old

    • stop the world
    • 老年代多线程收集
    • 标记-整理算法
    • 适合吞吐量优先的场景
  • CMS

    • 标记-清除算法

    • 过程步骤

      • 初始标记

        • stop the world
        • 标记GC Roots能直接关联的对象
      • 并发标记

        • GC Roots Tracing
      • 重新标记

        • stop the world
      • 并发清除

    • 比较

      • 优点

        • 并发收集
        • 低停顿
      • 缺点

        • cpu资源敏感

        • 本次无法处理浮动垃圾

          • 并发清理阶段产生的垃圾本次无法回收
        • 无法解决内存碎片

  • G1

    • 停顿时间更可控

工具

jps(虚拟机进程状态)

jstat(虚拟机统计信息监控)

jinfo(配置信息)

jmap(内存映像)

jhat(虚拟机堆转储快照分析)

jstack(Java堆栈跟踪)

JConsole

JVisualVM

类加载机制

类加载步骤

  • 加载

    • 数据来源

      • zip包读取
      • 网络读取
      • 计算生成
      • 文件生成
      • 数据库读取
      • .......
  • 验证

    • 文件格式验证

      • 魔数(0xCAFEBABE)
      • 主、次版本号
      • 常量类型是否支持
      • 常量索引是否不存在
      • 常量是否符合utf编码
      • Class文件各部分是否有被删除或者附加其他的信息
      • .........
    • 元数据验证

    • 字节码验证

    • 符号引用验证

  • 准备

  • 解析

    • 类和接口解析
    • 字段解析
    • 类方法解析
    • 接口方法解析
  • 初始化

  • 使用

  • 卸载

类加载器

  • 启动类加载器(Bootstrap ClassLoader)

  • 其他类加载器

    • 扩展类加载器(Extension ClassLoader)

    • 应用程序类加载器(Application ClassLoader)

      • 自定义类加载器1(User ClassLoader)
      • 自定义类加载器2(User ClassLoader)
      • 自定义类加载器3(User ClassLoader)
      • 自定义类加载器......(User ClassLoader)
  • 双亲委派模型

    • 一个类加载器收到类加载的请求,他首先不会自己去尝试加载这个类,他会把这个请求委派给父类加载器去完成,当父类反馈无法加载时,子类才会去尝试加载
    • 启动类加载器 <- 扩展类加载器 <- 应用程序类加载器 <- 自定义类加载器
posted @ 2022-03-29 10:58  shenjie2017  阅读(22)  评论(0编辑  收藏  举报