Java内存回收和常用算法

愿天堂没有BUG

共 1812字,需浏览 4分钟

 ·

2021-05-14 20:17

1.什么是垃圾?(Java中)

(1)一个对象没有任何引用指向这个对象

(2)几个对象之间互相循环引用,但是没有引用指向这个循环,那这个几个对象属于一堆垃圾

总结一句话:没有任何引用指向的一个对象或者多个对象


2.如何定位垃圾?

(1)reference count(引用计数):

对于对象进行一个引用的标记,有两个引用它的就标记为2,没有引用它的就标记为0,但是这种对于循环的引用的垃圾是无法回收的,这样就会发生内存泄漏

(2)Root Searching(根可达算法):

根据根对象一步一步去找引用的对象,最终没有找到的都被认为是垃圾


根对象包括:线程栈变量,静态变量,常量池,JNI指针

以下是java中的原话:



3.常见的垃圾回收算法

Mark-Sweep(标记清除)

Coping(拷贝)

Mark-Compact(标记压缩)


(1)Mark-Sweep——缺点:位置不连续,产生碎片


(2)Coping——缺点:没有碎片,但是浪费空间


(3)Mark-Compact——没有碎片,也不浪费空间,但是效率较低,比copy略低

有用的部分都压缩到最前面,空着的部分放在最后面,不碎片化,也不浪费空间



4.JVM内存分代模型(用于分代垃圾回收算法)

1.部分垃圾回收器使用的模型

2.新生代+老年代+永久代(1.7)/元数据区(1.8)Metaspace

(1)永久代和元数据区都是用来装class对象的

(2)永久代必须指定大小限制,元数据是可以设置,也可以不设置,无上限(受限于物理内存)

(3)jdk1.7版本的字符串常量是存在永久代的,1.8版本的时候是存在堆里

(4)MethodArea(方法区)是一种逻辑概念,在jdk1.7版本上对应的是永久代,在jdk1.8上对应的是元数据区

new-young:存活对象少,使用copy算法,效率高

old:垃圾少,一般使用mark-compact,g1使用copy

在java1.7中还有permanent算法

3.堆内存逻辑分区


new一个对象,直接去找伊甸区,如果new的对象太大,伊甸区装不下,直接进入老年代

YGC使用拷贝算法,FGC使用标记压缩算法,YGC虽然无法避免但是效率较高,FGC效率较低

(1)新生代=Eden + 2个suvivor区

  1. YGC回收之后,大多数的对象(90%)会被回收,活着的进入s0再次YGC,活着的对象eden + s0 -> s1再次YGC,eden + s1 -> s0年龄足够 -> 老年代 (老版的垃圾回收器:15岁,15岁即回收15次,为什么是15次呢,因为在一个对象的头部有4位来代表它的年龄,这个4位代表的最大数就是15, CMS垃圾回收器:6岁)s区装不下 -> 老年代

(2)老年代

  1. 顽固分子老年代满了FGC Full GC

(3)GC Tuning (GC调优,假设使用的是Generation算法)

  1. 尽量减少FGCMinorGC = YGCMajorGC = FGC


5.Java到目前为止产生的10种垃圾回收器


垃圾回收器组合:

最早的jdk垃圾回收器的组合: Serial + Serial Old

常见的垃圾回收器组合Parallel Scavenge + Parallel Old


(1)Serial垃圾回收器


(2)Parallel Scavenge 年轻代 并行回收


(3)ParNew 年轻代 配合CMS的并行回收


(4)SerialOld


(5)ParallelOld


(6)Concurrent Mark Sweep(CMS) 老年代,并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)


(7)G1(10ms)



(8)ZGC (1ms) PK C++

(9)Shenandoah

(10)Eplison

这是一个空的GC,本身并没有做任何事情,只是用来调试jdk的,jdk11才有

jdk1.8 默认的垃圾回收:Parallel Scavenge + Parallel Old


6.GC概念




7.总结,内存分配流程图




8.JVM调优工具

arthas

Java VisualVM

jmap命令



9.GC调优日志详解


浏览 38
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报