返回

jvm垃圾回收

jvm垃圾回收相关

jvm垃圾回收

对象存活判断算法

引用计数算法

问题: 可能存在两个对象相互引用,导致无法回收,内存泄漏

根可达算法

维护引用的链表; 如果某个对象无法到达根节点,说明可以被回收

那么哪些对象是根对象呢?主要包含:JVM stack,native method stack,run-time constant pool(运行常量池里的对象),static references in method area(方法区里的静态引用),Clazz等。

垃圾回收算法

停顿时间(延时)吞吐量的权衡,没有最好,只有最适合当前业务场景的回收方式

  • 针对 堆内存回收;

  • 方法区

    • java 8 前 永久区(也参与垃圾回收,一样的算法,省事了,但是有默认最大内存限制,容易oom)
    • java 8 彻底抛弃了 永久区,叫元数据区,使用本地内存

分代收集理论

新生代

老年代

跨代引用: Remember set

标记清除

产生内存碎片,内存分配复杂了。 可能需要类似硬盘的 “分区空闲分配链表” 等复杂方式解决

Cms搜集器在old 区回收时采用, 但是内存碎片达到一定量,会采取一次标记整理。(和稀泥的做法,结合两者,)

标记复制

一般用于新生代回收: Serial ParNew 的新生代采用该算法

scurvivorRadio Ēden survivor survivor 8:1:1

对象存活率较高时,需要更多的复制操作,效率会降低

标记整理

用于old区:

相对于 标记清除, 标记后,需要移动:将存活的对象移动到内存区域的一端。

  • 移动:增大的延迟,stw时间长些,但解决了内存碎片,内存分配复杂的问题,可以提高吞吐量。

  • 不移动:降低了延迟,但内存碎片,内存分配复杂, 吞吐量有所下降。

垃圾回收器

  • 对于新生代一般时使用标记复制算法

  • 对于老年代一般使用标记整理算法 (CMS除外)

image-20210916161350325

Serial收集器

  • 串行

ParNew收集器

  • 并行

Parallel Scavenge收集器

-XX:+UseParallelGC -XX:+UseParallelOldGC

  • 调整方式

    1.手动调整 -Xmn -Xms -XX:NewRatio=N 手动指定堆内存大小和代空间比例,一般要多次试验 2.自动参数调整 -XX:MaxGCPauseMillis=N 可接受最大停顿时间 -XX:GCTimeRatio=N 可接受GC时间占比(目标吞吐量) 吞吐量=1-1/(1+N)

  • 并行

  • 尽可能可以控制吞吐量 也叫 吞吐量优先收集器

-XX:+UseAdaptiveSizePolicy 默认开启的

Serial Old收集器

用于old区:串行

Parallel Old收集器

用于old区:并行

CMS收集器

-XX:+UseParNewGC -XX:+UseConcMarkSweepGC

  • 尽可能缩短垃圾回收时,用户线程的停顿时间

  • 和ParNew收集器配合:

Garbage First (G1)收集器

内存分配与回收策略

  1. 对象优先在Edem区分配

  2. 大对象直接进入老年代

  3. 长期存活的对象进入老年代

    • 每个对象有个年龄计数器 MinorGC一次,加1

    • -XX:MaxTenuringThreshold=X X默认是15, 15次后进入老年代

  4. 动态对象年龄判断

    -XX:TargetSurvivorRatio 目标存活率,默认为50%

    survivor中相同年龄的对象大小之和大于TargetSurvivorRatio后,大于等于该年龄的都晋升到老年代。

  5. 空间分配担保

相关应用

查看当前java版本使用的GC

java -XX:+PrintCommandLineFlags -version

[root@sd01 ~]# java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=128167296 -XX:MaxHeapSize=2050676736 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

img

UseParallelGC 按道理时使用 Parallel Scavenge + SerialOld,但后来P araller old出现后,实际默认时用的Parallel Scavenge + Parallel Old

默认堆大小

什么是jdk1.8默认堆大小? (MaxHeapSize)

就是使用java -jar 并且没有手动指定-Xmx参数的启动的进程使用的堆的大小,就是用的默认jdk堆的大小。

这个默认的堆大小是取决你服务器的物理内存,假如服务器内存大于1GB,则使用1/4的服务器物理内存作为jvm的堆内存大小。

eg:服务器内存4GB 则默认堆大小为1GB

java -XX:+PrintFlagsInitial

配置试例

 java -Xms1600m -Xmx1600m -Xmn800m -Xloggc:/xxx/logs/xxx_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=20 -XX:GCLogFileSize=100M -Dprofile=prod -jar /xxx/xxx-1.0.0-SNAPSHOT.jar

-Xms: //堆内存初始化大小 -Xmx: //堆最大可用内存 -Xmn: //新生代堆最大可用内存 -XX:UseParallelGC //使用gc的类型

-XX:SurvivorRadio//设置新生代中:Eden空间、SurvivorRadio From空间、SurvivorRadio To空间的占比 -XX:NewRatio //设置新生代空间和老年代空间的占比 -XX:+PrintGC //每次触发GC的时候打印相关日志 -XX:+PrintGCDetails //打印详细Gc日志

-XX:+UseGCLogFileRotation

-XX:NumberOfGCLogFiles

-XX:GCLogFileSize

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy
本站访问量:   您是本站第 位访问者