1:什么是垃圾&
对于java来说,没有引用指向的对象就是垃圾,没有作用还耗费内存
多个对象循环引用的也是垃圾
2:java如何定位垃圾(什么对象是垃圾)
1:引用计数器(被使用就加一,被释放引用就减一,缺点是不能解决循环依赖)
2:根可达性算法(从被根上开始寻找,寻找它们的其他引用,寻找结束后,没被找到的对象(没有被引用的对象)就是垃圾对象) 问题 那些是根
3:常见的垃圾回收算法
1:标记清除(将被标记的对象进行回收,由于内置不连续,会产生内存碎片)
2:标记整理/拷贝算法(内存一分为二,将不需要回收的对象移动在另一块区域,然后将需要回收的对象进行回收,没有碎片,但是浪费空间)
3:标记压缩(使用存活的对象直接向前覆盖垃圾对象,没有碎片但是效率低下)
需要根据具体情景使用
4:jvm内存模型
1:新生代+老年代+永久代(1.7)/元数据区(1.8)
1.永久代,元数据区 都是存放class
2.永久代必须设定大小,元数据区可以不设定大小,上限取决于物理内存
3.字符串产量 1.7存放于永久代,1.8存放于堆
新生代(1)YGC(80%的对象是垃圾) copy | 老年代(3)FUll GC Mark compact | |||||
eden(8) | survivor1(1) | survivor2(1) | 终身代(old) | |||
进行垃圾回收时将数据移动到 s1,然后将本区集体回收,这样效率快,每个线程在eden都有一块区域,用来存放对象。 | 进行垃圾回收时会将存活的对象和eden一起移动到s2 | 进行垃圾回收时会将存活的对象和eden一起移动到s1 | tenured(里面都是存放顽固分子) 老年代满了,来一次full gc(回收老年代的同时,年轻代也会进行GC) | |||
创建对象的时候优先放入eden,如果eden放不下那么直接放入老年代,存活时间长(15次垃圾回收后)的对象直接放入老年(不同垃圾回收器的次数不一样)代,垃圾回收的同时会引发stw(程序停顿) 年老代用的是:标记清除与标记压缩 年轻代用的是复制算法, |
5:GC Turing
1.尽量减少FUll GC
2.MinorGC=YGC
3.majorGC=FGC
6:常见的垃圾回收器(Garbage Collectors)
发展路线:随着内存越来越大的过程而演进
从分代算法演化到不分代算法
永久代
JVM 里的永久代就是 前面的方法区。永久代里就是放一些类信息的。
年轻代
Serial 单线程 串行 stw(停顿所有用户线程)程序停顿时间长 几时兆
Parallel Scavenge 多线程 并行 stw(程序停顿时间长) 几个G
ParNew == Parallel Scavenge (和cms配合使用)
老年代
CMS 并发回收,(承前启后的垃圾回收,进行垃圾回收的同时,应用线程也能同步运行,stw现象短,200ms内)
三色标记算法-》错标
初始标记和重新标记都会引发stw(短暂的stw,因为只要找到跟节点就行),并发标记时,用户线程不会停止
问题:
1:什么是根节点
2:如果在在某个对象被确认为垃圾后,又有另一个引用指向它,那么该对象就不是垃圾了,这种情况如何处理?(重新标记)
Serial Old 单线程 串行
Parallel old 多线程 并行
不分代
G1(10ms) (三色标记+SATb)逻辑分代,物理不分代。 优先清理垃圾最多的小块
ZGC颜色指针(1ms) 逻辑物理都不分代
shenandoal 逻辑物理都不分代
Epsilon 做测试使用实际不回收
1.8 默认的垃圾回收器 Parallel Scavenge+Parallel old
适用范围
Serial算法 几十兆
Parallel 算法 几个G
Cms 几十个G
G1 上百G
ZGC ---shenandoal T
常用命令
java -xx:PrintCommandLineFlags 查看java程序启动的时候使用了那些命令参数
-xx:+PringFlagsFinal 最终参数值
-xx: +PrintFlagsInitial 默认参数值