GC的基础知识
1.1 什么是内存垃圾?
c 语言中申请内存的方式:
申请内存 malloc 释放内存:free
c++中申请内存的方式:
申请内存:new 释放内存:delete
Java中申请内存的方式:
申请内存:new 释放内存:自动回收
1.2 Java中的自动内存回收有什么好处?
编程上简单,系统不易出错
手动释放内存,容易出两种类型的错误:
1.忘记回收资源,会导致内存泄漏
2.多次回收,导致资源使用时异常
Java中的自动回收机制保证垃圾回收
1.3 Java中什么被称为垃圾?
一个对象没有任何引用,则称这个对象为垃圾数据
好多个对象互相之间有引用,但是没有其他任何对象指向这个循环对象,称之为一堆垃圾
1.4 如何找到垃圾?
reference count:引用计数 算法
计算这个对象几个指向,什么时候指向这个对象的引用为0了,这个对象为垃圾
循环引用的垃圾无法识别
root searching:根可达算法(根搜索算法)
可解决循环引用的对象垃圾问题
什么是根对象?
当程序运行起来以后,根对象指 GC roots 线程栈变量,静态变量,常量池,JNI变量
没有根对象指向的都是垃圾
1.5常见的垃圾回收算法有那些?
Mark-Sweep(标记清除)
标记后之后进行清除,对内存中的垃圾进行标记为非垃圾区域,然后在对垃圾进行清楚
优缺点:位置不连续,产生碎片内存
Copying(拷贝)
对内存进行二分,然后将一半中的有效数据拷贝到另一半空闲区域中,最后对整个拷贝完的区域进行整体清除
优缺点:没有碎片,效率高,连续的内存空间 浪费内存空间
Mark-Compact(标记压缩)
一个内存里面,分配的对象后,回收的时候,将对象标记为垃圾,将后面的对象拷贝到这里来,在做标记清除的时候,也做了一个压缩,将有用的对象迁移到一块,合理利用内存空间,连续内存
优缺点:效率比copying低 任何一块碎片挪动都需要线程同步,效率低,单线程整体效率更低
1.6 生产环境中的 Jvm算法
JDK 1.7/1.8
把Jvm分成不同的代,也叫区域,以1.8为例
1.7 Java中JVM的分代模型,部分垃圾回收器中,使用的模型
new / young(新生代)
old(老年代)
永久代(1.7) / 元空间(1.8) Metaspace
都是装-Class对象的以及部分常量池的内容
永久代必须指定大小限制,后期限制系统的使用大小,会产生永久代的内存溢出
元空间可以设置大小,也可以不设置,无上限可以设置下限(受限于物理内存的大小)
字符串常量:1.7存在永久代,1.8中存在于堆里
MethodArea逻辑概念
1.7-永久代
1.8-元空间
1.8 堆内存的详细的逻辑分区
堆内存分为新生代和老年代
新生代里分为两类三个区域=eden()伊甸区 + surcicor 两个
eden()伊甸区 一个
创建的对象,先存入Eden区,如果伊甸区放不下,直接存入老年代
surcicor 两个
有利于垃圾回收
新生代的垃圾存在一个特点:YGC回收,特点:进行依次YGC回收之后,大多数的对象会被回收
第一次YGC new 新生代 对象 大多数会直接被清除 选择算法的时候,选择Copying回收算法
活着的对象进入s0,再次YGC的,活着的对象,包括s0区域,有效对象全部拷贝到s1中,
再次YGC后,eden+s1–>s0
最后年龄足够了,进入老年代(其中YGC的时候,对应的区域空间不足,直接进入老年代)
年龄足够->老年代(15 cms 6)
老年代
顽固对象
老年代满了,触发FGC (Full GC)
GC Tuning(Generation) 尽量减少FGC
FGC的效率非常的差,会产生停顿现象,一般尽量不要产生FGC,会产生压缩算法,效率较低
完成不产生的概率也不大,不过可以降低YGC的频率越低越好
概念:
MinorGC =YGC
MajorGC =FGC
1.9 常见的垃圾回收器 Garbage Collectors
目前的JDK的13为止,Java一共产生了10中垃圾回收器
Young:年轻代
Serial:Java 虚拟机规范中说明( 串行回收)
本来程序正常运行,伊甸区满了,触发YGC的时候,停下所有的运行线程,回收完所有垃圾,运行线程继续进行
ParNew:并行回收
配合CMS的并行回收
Parallel Scavenge:并行回收
多个线程同时进行回收
Old: 老年代
CMS Concurrent mark sweep
并发的垃圾回收和应用程序同时运行,降低STW的时间(200ms)
Serial Old 将Serial的对象放到Old区
Parallel Old 将Parallel的对象放到Old区
在CMS 的基础上,开发的更高效的回收算法
G1:效率达到(10ms)
ZGC:效率达到(1ms) PK C++ 实验期
Shenandoah 实验期
不会用
Epsilon:JDK调试debug的时候使用,JDK开发人员用的内部GC的,一般不用
1.8 默认的垃圾回收器 Parallel Scavenge +Parallel Old
使用多线程的新生代和多线程的老年代
2.0 生产环境下的垃圾回收器组合
jvm参数分类:
标准参数: -开头
非标准命令:-X开头
不稳定: -XX开头
常用的命令:
-XX:++ProntCommandLineFlags 使用参数值
-XX:+PrintFlagsFinal 最终参数值
-XX:+PrintFlagsInitial 默认参数值