浅析JVM垃圾回收机制

首先我们需要知道Java的内存分配与回收全部由JVM垃圾回收机制自动完成。每种JVM实现可能采用不同的方法实现垃圾回收机制。在收购SUN之前,Oracle使用的是JRockit JVM,收购之后使用HotSpot JVM。目前Oracle拥有两种JVM实现并且一段时间后两个JVM实现会合二为一。HotSpot JVM是目前Oracle SE平台标准核心组件的一部分。市面上探讨垃圾回收机制,默认都是基于HotSpot JVM的。Ok,我们切入正题,先来看下JVM的内存区域模型,

这张图非常直观的展示了JVM的内存区域划分,我们关注的GC在哪里呢?答案在下面这张图里面。

对比两张图,我们发现,垃圾收集器跟jit编译器一起构成了JVM的执行引擎,gc的“势力范围”是哪里呢?且看下图

再次强调这是hotspot的堆模型,其他JVM(如JRockit、IBM J9等)是不存在永久代的概念的,有趣的是在Java8中,hotspot也将永久代取消了,改为了metaSpace,直接采用本地内存,这也减轻了堆的压力。

我们暂且看应用更为广泛的JDK8之前的堆分区:

1、新生代(Young Generation):绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程我们称之为”minor GC“。

Eden空间(Eden space,任何实例都通过Eden空间进入运行时内存区域)

S0 Survivor空间(S0 Survivor space,存在时间长的实例将会从Eden空间移动到S0 Survivor空间)

S1 Survivor空间 (存在时间更长的实例将会从S0 Survivor空间移动到S1 Survivor空间)

2、老年代(Old generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为”major GC“(或者”full GC“)

S1中的实例,如果存活时间足够长将提升到老年代(Old Generation)。

3、永久代(Permanent Generation)包含类、方法等细节的元信息,也就是JVM内存结构中的方法区,他用来保存类常量以及字符串常量。因此,这个区域不是用来永久的存储那些从老年代存活下来的对象。这个区域也可能发生GC。并且发生在这个区域上的GC事件也会被算为major GC。hotspot由于把GC扩展到方法区,所以把方法区抽象成永久代,作为堆的逻辑结构。再补充一点,著名的字符串常量池在JDK7之前,就在永久代里面,JDK7之后从永久代中挪出到正经的堆中了。毕竟永久代实际上并不在堆里,只是hotspot为了扩张GC的势力范围,才有了上面的那张图。

下面我们来看看新生代的GC过程:

新生代是用来保存那些第一次被创建的对象,他可以被分为三个空间

一个伊甸园空间(Eden )

两个幸存者空间(Survivor )

一共有三个空间,其中包含两个幸存者空间。每个空间的执行顺序如下:

1、绝大多数刚刚被创建的对象会存放在伊甸园空间。

2、在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。

3、此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。

4、 当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。

5、在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。

如果你仔细观察这些步骤就会发现,其中一个幸存者空间必须保持是空的。如果两个幸存者空间都有数据,或者两个空间都是空的,那一定标志着你的系统出现了某种错误。

时间: 2024-10-10 01:41:05

浅析JVM垃圾回收机制的相关文章

JVM内存管理和JVM垃圾回收机制

JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采用不同的垃圾回收机制. AD: 你对JVM内存组成结构和JVM垃圾回收机制是否熟悉,这里和大家简单分享一下,希望对你的学习有所帮助,首先来看一下JVM内存结构,它是由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示. JVM学习笔记 JVM内存管理和JVM垃圾回收 JVM内存组成结构 JVM内存

java JVM垃圾回收机制

Java语言出来之前,大家都在拼命的写C或者C++的程序,而此时存在一个很大的矛盾,C++等语言创建对象要不断的去开辟空间,不用的时候有需要不断的去释放控件,既要写构造函数,又要写析构函数,很多时候都在重复的allocated,然后不停的~析构.于是,有人就提出,能不能写一段程序在实现这块功能,每次创建,释放控件的时候复用这段代码,而无需重复的书写呢? 1960年 基于MIT的Lisp首先提出了垃圾回收的概念,用于处理C语言等不停的析构操作,而这时Java还没有出世呢!所以实际上GC并不是Jav

JVM垃圾回收机制入门

前言 数据库是大家会普遍重视的一个领域,异步通信一般用不到,虚拟机在大部分时候不会出问题,常被人忽视,所以我打算先学习虚拟机,从零单排Java高性能问题. 堆内存存储结构 Java6是以年代来规划内存的,而Java7的G1收集器则相反,这里以Java6为准. Survivor1和Survivor2是一样大的,必有一个始终为空,容量小于Eden. 垃圾回收机制 年轻代采用复制算法,当回收时,将Eden和Survivor中还存活的对象一次性地复制到另外一块Survivor上,然后清理掉Eden和刚才

JVM垃圾回收机制(一)

垃圾回收器 垃圾回收器主要负责: 1. 分配内存: 2. 保证所有正在被引用的对象还存在在内存中: 3. 回收不再被程序所引用的对象所占内存: Hotspot VM提供的垃圾回收器是一个分代的垃圾回收器(Generational GC),它将内存划分为不同的阶段,即不同生命周期的对象被放置在不同的内存空间中.这样的设计是基于弱年代假设(Weak Generational Hypothesis):大多数对象会很快变得不可达,只有很少有老对象指向新对象的引用.这种方式可以减少垃圾回收的停顿时间以及大

JVM垃圾回收机制总结(3) :按代垃圾收集器

为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的 . 因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象.线程.Socket连接,这 类对象跟业务直接挂钩,因此生命周期比较长.但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对 象,由于其不变类的特性,系统会产生大量的这些对象,有些

JVM 垃圾回收机制( 一) 回收对象的判定

关于JVM 的垃圾回收机制,我们一般都没过多深入,因为JAVA 和 C++ 的一个很大区别就是,JAVA 帮我们做了垃圾回收,而不用像C++ 那么样手动进行回收,当然任何自动的东西都存在一定弊端,比如机器人,即使自动程度很高,但是在处理某些感情问题上,肯定处理上就会有遗漏,开个玩笑啦, 下面我们先来了解一下JVM 的垃圾回收是怎么回事. 一.如何判断对象已经死亡 JVM 会回收那些不在使用的对象,或者说是已经死亡的对象,从而达到节省空间的目的,那么我们肯定的判断哪些对象已经死了,不在使用呢? 1

JVM垃圾回收机制与算法

JVM内存由几个部分组成:堆.方法区.栈.程序计数器.本地方法栈 JVM垃圾回收仅针对公共内存区域,即:堆和方法区进行,因为只有这两个区域在运行时才能知道需要创建些对象,其内存分配和回收都是动态的. 一.垃圾回收策略 1.1分代管理 将堆和方法区按照对象不同年龄进行分代: (Young Generation and Old Generation)堆中会频繁创建对象,基于一种分代的思想,按照对象存活时间将堆划分为新生代和旧生代两部分,并不是一次垃圾回收新生代存活的对象就放入旧生代, 而是要经过几次

简单测试JVM垃圾回收机制 System.gc()方法

简单的写一个方法测试Java的垃圾回收机制 System.gc()可以提醒JVM虚拟机去进行垃圾回收了,但是不一定成功. /** * 覆写Object中的finalize()方法 */ public class LJ { @Override protected void finalize() throws Throwable { System.out.println("垃圾正在回收..........."); } } public class GCDemo { /** * @param

深入JVM垃圾回收机制,值得你收藏

JVM可以说是为了Java开发人员屏蔽了很多复杂性,让Java开发的变的更加简单,让开发人员更加关注业务而不必关心底层技术细节,这些复杂性包括内存管理,垃圾回收,跨平台等,今天我们主要看看JVM的垃圾回收机制是怎么运行的,希望能够帮到大家, 哪些对象是垃圾呢? Java程序运行过程中时刻都在产生很多对象,我们都知道这些对象实例是被存储在堆内存中,JVM的垃圾回收也主要是针对这部分内存,每个对象都有自己的生命周期,在这个对象不被使用时,这个对象将会变成垃圾对象被回收,内存被释放,那么如何判断这个对