性能测试全栈笔记:59.Jvm内存结构和垃圾回收

作者: admin 分类: 性能专题 发布时间: 2023-01-21 15:13

本期专题:性能测试全栈笔记:59.Jvm内存结构和垃圾回收

本期内容偏理论,较为枯燥,可自行选择学习

1.Java内存管理机制

  • Java采用了自动管理内存的方式
  • Java程序是运行在JVM之中的
  • Java的跨平台的基于JVM的跨平台特性
  • 内存的分配和对象的创建是在JVM中
  • 用户可以通过一系列参数来配置JVM

2.Java运行时区域

说明:主要关注方法区、虚拟机栈、堆

3.Java内存结构

说明:左边是栈内存,中间是堆内存,右边是永久代

4.栈内存

  • 线程私有
  • 生命周期和线程相同
  • 主要存放内容
    • 基本数据类型(int,char,float,double…)
    • 对象的引用,指向了对象在堆内存中起始地址
    • 通过-Xss参数配置内存的分配和对象的创建是在JVM中

5.堆内存

  • 堆内存是JVM中空间最大的区域
  • 所有线程共享堆
  • 所有的数组以及内存对象的实例都在此区域分配
  • 堆内存大小通过参数进行配置
    • -Xmx:最大堆内存
    • -Xms:最小堆内存
说明:左边新生代、右边老年代
  • 堆内存 = 年轻代+老年代
  • 年轻代 = Eden+Survivor
  • Survivor = From Space(s0)+To Space(s1)

6.堆内存构成

  • 堆内存构成:
  • 新生代:包括三块区域,eden、from survivor(s0)、to survivor(s1)
  • 老年代:old gen

7.永久代(PermGen)

  • 永久代也叫(Method Area)
  • 各线程共享,主方法区要存放类信息、常量、静态变量,如:public static int a = 10
  • 垃圾回收行为比较少见

8.JVM结构总结

  • 年轻代 = Eden+Survivor
  • Survivor = From Space(s0) + To Space(s1)
  • 年轻代 = Eden+From Space+To Space
  • 堆内存 = 年轻代+老年代
  • 堆内存=Eden+From Space+To Space+老年代

9.Java8新变化

  • Java8从Jvm中移除了PermGen,使用Metaspace(元空间)来代替永久代
  • Metaspace不存在Jvm中,而是存在本地内存中
  • 配置元空间初始值和最大值参数:
    • -XX:MetaspaceSize=64m
    • -XX:MaxMetaspaceSize=64m

10.垃圾回收-GC

三个问题:

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收?

11.YoungGC和FullGC

  • 新生代引发的GC叫YoungGC
  • 老年代引发的GC叫FullGC
  • FullGC会引起整个Jvm的用户线程暂停,待垃圾回收完毕后,才继续运行

12.对象存活状态

  • 确定对象“存活”还是“si去”
    • 引用计数算法
    • 根搜索算法(GC Roots)
  • 引用的定义
    • 如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表一个引用

13.永久代的垃圾回收

永久代回购“性价比”比较低

主要回收

废弃的常量

无用的类

  • 类的所有实例都已经被回收
  • 加载该类的ClassLoader已经被回收
  • 该类的Class对象没有在任何地方被引用

14.堆垃圾回收算法

  • 标记-清除算法
  • 复制算法
  • 标记-压缩算法
  • 分代收集算法

15.标记-清除算法(Mark-Swap)

  • 特点:
    • 分为“标记”和“清除”两个阶段
    • 标记完成后,统一回收
  • 缺点:
    • 效率,标记和清除过程效率都不高
    • 空间,标记清除后会产生大量不连续的内存碎片

16.复制算法

  • 特点:
    • 内存分为相等的两块
    • 当一块内存用完,将存活对象复制到另外一块中,
    • 原内存一次性清理掉
    • 复制时按照顺序分配内存,无内存碎片问题
    • 新生代使用此算法
  • 缺点:
    • 将内存分为两半,利用率低

17.标记-压缩算法

  • 特点:
    • 先对存活对象进行标记
    • 让所有存活对象向一边移动
    • 清理掉存活对象边界外的所有内存
  • 注:老年代使用此算法

18.分代收集算法

  • 当代的商业虚拟机都采用“分代收集”
  • 根据对象的存活周期的不同将内存划分成几块,一般Java堆分为新生代和老年代
  • 新生代采用复制算法
  • 老年代采用标记-压缩算法

19.垃圾收集器

  • 垃圾收集器是内存回收算法的具体实现
  • 没有完美的收集器
  • Jvm不同的区域可以采用不同的垃圾收集器组合,主要有:
    • Serial收集器(串行)
    • ParNew收集器(并行)
    • CMS收集器(并发)
    • G1(时间优先)

20.Seria收集器

  • 单线程收集器
  • 用户线程全部停止(Stop the world)
  • Client模式下,新生代默认收集器
  • 优点:简单、高效

21.ParNew收集器

  • 并行收集器,Serial收集器的多线程版本
  • Server模式下Jvm默认的新生代收集器
  • 默认开启的垃圾回收线程与cpu核数一致

22.CMS收集器

  • 并发收集器(ConcurrentMarkSweep)
  • 采用了标记-清除、标记-压缩算法
  • 并发收集、低停顿
  • 缺点:
    • 消耗cpu
    • 会产生内存碎片
    • 浮动垃圾(Concurrent Mode Failure)

23.内存溢出

  • 堆内存溢出
    • 堆内存中存在大量对象,这些对象都有被引用,当所有对象占用空间达到堆内存的最大值,就会出现内存溢出
    • OutOfMemory:Java heap space
  • 永久代溢出
    • 类的一些信息,如类名、访问修饰符、字段描述、方法描述等,所占空间大于永久代最大值,就会出现OutOfMemoryError:PermGen space
  • 检测方法
  • JDK/bin目录下有很多检测工具
  • 图形界面:
    • Jconsole
    • Jvisualvm
  • 命令行工具
    • Jstat –gcutil pid 1000 100
    • Jmap –histo pid | head -20
    • Jmap –heap pid
  • FullGC频率:建议单次FullGC时间<200ms

24.垃圾回收和CPU使用率

25.内存泄露和TPS

26.JVM常见参数

  • -Xms2048m,初始堆大小,建议<物理内存的1/4,默认值为物理内存的1/64
  • -Xmx2048m,最大堆大小,建议与-Xms保持一致,默认值为物理内存的1/4
  • -Xmn512m,新生代大小,建议不超过堆内存的1/2
  • -Xss256k,线程堆栈大小,建议256k
  • -XX:PermSize=256m,永久代初始值,默认值为物理内存的1/64
  • -XX:MaxPermSize=256m,永久代最大值,默认值为物理内存的1/4
  • -XX:SurvivorRatio=8:年轻带中Eden区和Survivor区的比例,默认为8:1,即Eden(8),From Space(1),ToSpace(1)
  • -XX:+UseConcMarkSweepGC:开启CMS垃圾回收器

27.G1垃圾回收

  • G1全称是Garbage First Garbage Collector,在jdk1.7u4中开始支持。Java9中默认的垃圾收集器
  • G1的设计原则就是简化性能优化的复杂性

本节详细内容请参考:深入理解Java虚拟机:JVM高级特性与最佳实践-第3版(pdf版)

资源下载
免费资源
深入理解Java虚拟机:JVM高级特性与最佳实践-第3版(pdf版)点击下载
如下载链接失效请联系客服QQ:932875327;微信:rlczhouxiong

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注