java gc回收区域_Java内存区域和GC回收器

Java内存区域

cde6890ab9ed2c32bdf5677caaf4fab8.png

57819310d28da4e49cd599fc3787b5c9.png

程序计数器线程私有。是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器

Java虚拟机栈线程私有,生命周期与线程相同。

Java虚拟机栈描述的是Java方法执行的内存模型:每个方法执行的同时会创建一个栈帧。 对于我们来说,主要关注的stack栈内存,就是虚拟机栈中局部变量表部分。

栈帧栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素。

栈帧用于存储局部变量表、操作数栈、动态链接、方法返回等信息。 每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

a40a0211a564c29a6ce89c3dbb9e30a5.png

本地方法栈线程私有,与虚拟机栈相似,区别在于虚拟机栈为虚拟机执行Java方法服务(也就是字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务。

堆线程共享,在虚拟机启动时创建

堆是虚拟机所管理的内存中最大的一块。此内存区域的唯一目的就是存放对象实例和数组,几乎所有的对象实例和数组都在这里分配内存。

Java堆是垃圾收集器管理的主要区域,也称为GC堆。

如果在堆中没有内存完成实例分配,并且堆上也无法再扩展时,将会抛出OutOfMemoryError异常。

内存泄露和内存溢出

内存泄露 : 指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用,可用内存越来越少。

内存溢出 : 指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于老年代或永久代垃圾回收后,仍然无内存空间容纳新的Java对象的情况。

方法区线程共享,又被称为静态区或永久区,是程序中永远唯一的元素存储区域

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

运行时常量池(Runtime Constant Pool)是方法区的一部分。

运行时常量池用于存放编译期生成的字面量和符号引用,这部分内容(也可以称为 .Class文件中的静态常量池)将在类加载后进入方法区的运行时常量池中存放。

GC算法

概述

JVM 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理。因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的.

对象存活判断

引用计数

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。

可达性分析(Reachability Analysis)

从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。

垃圾收集算法

标记-清除算法

它是最基础的收集算法,算法分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

主要缺点效率不高

标记清除之后会产生大量不连续的内存碎片

77de3fd5e99a5d1c6d9b832650903e72.png

复制算法(用于新生代)

复制收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

优点实现简单,运行高效

不会产生内存碎片

缺点内存缩小为原来的一半

18e52980e8e6763243e3a7b7f52a9b7c.png

标记-整理算法(用于老年代)

复制收集算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。

根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

90d421c8b0fd4f0459ffec641626ca57.png

分代收集算法(结合使用)

GC分代的基本假设:绝大部分对象的生命周期都非常短暂,存活时间短。

分代收集(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。

垃圾收集器

如果说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现

b06721773f0693e96023498a2a922993.png

Serial收集器

新生代收集器,单线程,串行,使用停止复制算法。进行GC时需暂停其它工作线程。

ParNew收集器

新生代收集器,多线程,并行,使用停止复制算法。Serial收集器的多线程版,用多个线程进行GC,其它工作线程暂停,关注缩短垃圾收集时间。

Parallel Scavenge收集器

新生代收集器,多线程,并行,使用停止复制算法。关注CPU吞吐量,即运行用户代码的时间/总时间

CMS(Concurrent Mark Sweep)收集器

老年代收集器,多线程,并发。致力于获取最短回收停顿时间(即缩短垃圾回收的时间),使用标记清除算法,优点是并发收集(用户线程可以和GC线程同时工作),停顿小。

Serial Old收集器

老年代收集器,单线程收,串行,使用标记整理算法。

Parallel Old收集器

老年代收集器,多线程,并行,多线程机制与Parallel Scavenge差不多,使用标记整理算法。

G1收集器

G1是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器。与CMS收集器相比G1收集器有以下特点:

空间整合:

G1收集器采用标记整理算法,不会产生内存空间碎片。分配大对象时不会因为无法找到连续空间而提前触发下一次GC。

可预测停顿:

这是G1的另一大优势,降低停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值