JVM垃圾回收区域,垃圾回收算法概述

2022-05-13 12:41:26 浏览数 (1)

问题
  • JVM垃圾回收机制
  • GC发生在JVM哪部分
  • 有几种GC,它们的算法是什么?
JVM体系结构

image.png

GC发生在JVM哪部分?

发生堆和方法区

主要发生在堆中,堆区由所有线程共享,在虚拟机启动时创建。堆区主要用于存放对象实例及数组,所有new出来的对象都存储在该区域。

少部分发生在永久代

永久代的垃圾回收主要回收两部分内容:废弃常量无用的类

回收废弃永久代数据与回收Java堆中的对象非常相似。以常量池中字面量的回收为例,若字符串“abc”已经进入常量池中,但当前系统没有任何String对象引用常量池中的“abc”常量,也没有其他地方引用该字面量,若发生内存回收,且必要的话,该“abc”就会被系统清理出常量池。常量池中其他的类(接口)、方法、字段的符号引用与此类似。

无用的类需要满足3个条件:

(1)该类所有的实例都已经被回收,即Java堆中不存在该类的任何实例;

(2)加载该类的ClassLoader已经被回收;

(3)该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

jvm虚拟栈,本地方法栈,程序计数器不需要进行垃圾回收,因为他们的生命周期是和线程同步的,随着线程的销毁,他们占用的内存会自动释放。所以,只有方法区和堆区需要进行垃圾回收,回收的对象就是那些不存在任何引用的对象。

堆中内存分布:

针对于分代收集算法来定义分为新生代和老年代

其实新生代和老年代就是针对于对象做分区存储,更便于回收等等

堆大小 = 新生代 老年代。默认下,新生代 ( Young ) = 1/3 的堆空间大小,老年代 ( Old ) = 2/3 的堆空间大小

新生代又分为Eden和Survivor两个区。加上老年代就这三个区。数据会首先分配到Eden区 当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象)。),当Eden没有足够空间的时候就会 触发jvm发起一次Minor GC。如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空 间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代 中了,当然晋升老年代的年龄是可以设置的。

为什么要进行分代?

隔离存活周期长的和短的对象,快速回收大量短存活周期对象。

新生代使用的GC算法
  • 引用计数

已淘汰

  • 复制算法

复制算法

老年代使用的GC算法
  • 标记清除

image.png

  • 标记压缩(对比普通标记清楚,它将需要清除的移动到一块连续的内存区域,清除的时候不会造成内存碎片)

image.png

  • 标记清除压缩 标记清除,标记压缩结合使用,先多次进行标记清除,产生许多内存碎片,然后对碎片清理(多次FULL GC之后再压缩),相对标记压缩减少了压缩次数减少了许多移动成本

GC算法(引用计数/复制/标清/标整)是内存回收的方法论,垃圾收集器就是算法落地实现。

七大垃圾回收器

0 人点赞