JVM的内存回收及常见算法小结

什么样的对象应该被回收?

某个对象不再被栈直接或间接地引用,此时就应该被回收了。

o被指向null的时候,new Object()创建的对象就不在被栈引用了,可以被回收。

p1和personList均不再指向第一个Person对象的时候,第一个Person对象、list对象可以被回收。

经历前面的几个阶段,内存引用是这样的情况。

p1 = null后,p1曾经指向的对象虽然不再被栈直接引用,但是仍然间接通过persons引用。

此时p1指向的对象和list指向的对象都可以被回收了。

怎么样确定哪些需要回收?

对我们仍然需要使用的对象进行标记,回收没有标记的对象。

以此为例,如何进行标记的呢?

垃圾回收进行之前,所有对象的标记位是0

如果仅仅标记栈直接引用的对象,p1就会被回收,但是p1间接被list引用,因此也被标记为1

标记算法

-Stop the World(GC Root可达性算法)

在进行上面的标记过程的时候,如果有新的对象被创建,而刚好被标记过程错过的时候,就可能错误地把有用的对象给回收掉,因为标记位是0.因此,Stop the World正如其名,将应用的核心线程停掉,开始专心标记。

-引用计数法

对对象进行引用数量的标记,没有引用的对象标记是0,有引用的对象标记是引用数量。清除标记为0的对象即可。但是引用计数法有个问题,无法解决循环引用的问题,导致内存泄露。

这里声明一个对象,内部包含一个跟自己一个类型的成员变量。

在执行第五行之前,两个对象的引用计数均为2,各自引用,加上n1和n2.

执行完第五六行以后,按道理,栈上已经不在引用这两个对象,可以被回收了,但是因为n1和n2相互引用,导致引用计数为1,无法正常回收。

清除算法

一般清除算法:直接将未标记的对象清理掉

经过清理,未标记的对象被回收。

但是存在内存碎片化的问题,只能从间隙处继续分配内存,

存在内存不连续的问题,内存空间浪费严重,容易oom

清除-整理算法:先清除没有标记的对象,然后将剩余的存活对象进行整理,让内存空间更加连续。

就是代价比较高,几乎需要移动所有的对象。

复制-清除算法:将活跃的对象复制到另一个内存区域,然后清除当前区域的所有对象!

完成复制后,清除原有的区域

这种算法的弊端就是需要更多的内存空间。

常见的GC类型

GC类别 新生代垃圾回收 老年代垃圾回收 特点
Serial GC 标记-复制&清除
标记-清除&整理

Stop the World

使用单个线程处理

适合小应用

Parallel GC Java 8默认垃圾回收器

Stop the World

使用多个线程处理

CMS GC 标记-复制&清除

(Stop the World)

接近并行的标记-清除

初始标记->并发标记

-> 并发预清理->可中断预清理->重新标记->并发清除->并发重置

G1 GC
更细粒度的逻辑分区,更小的停顿时间

采用复制&整理-清理的方式,优先回收垃圾最多的区域

对字符串的合并整理,多个相同的字符串合并到一起,移除冗余字符串对象

-XX:UseStringDeduplication
Z GC
不在维护映射,而是对象上保持一个标记来表示活跃对象

仅支持64位系统

采用重定位解决内存碎片化问题

Java 15

到此这篇关于JVM的内存回收及常见算法的文章就介绍到这了,更多相关JVM的内存回收内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 图解JVM垃圾内存回收算法

    前言 首先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的人都知道以下两点: JVM是做什么的 Java堆是什么 因为我们即将要讲的就是发生在JVM的Java堆上的垃圾回收,为了突出核心,其他的一些与本篇不太相关的东西我就一笔略过了 众所周知,Java堆上保存着对象的实例,而Java堆的大小是有限的,所以我们只能把一些已经用完的,无法再使用的垃圾对象从内存中释放掉,就像JVM帮助我们手动在代码中添加一条类似于C++的free语句的行为 然而这些垃圾对象是怎么回收的,现在不知道没关系,我们

  • JVM的垃圾回收算法工作原理详解

    怎么判断对象是否可以被回收? 共有2种方法,引用计数法和可达性分析 1.引用计数法 所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象时,就将计数器加一,引用失效时,计数器就减一.当一个对象的引用计数器为零时,说明此对象没有被引用,也就是"死对象",将会被垃圾回收. 引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象A引用对象B,对象B又引用者对象A,那么此时A,B对象的引用计数器都不为零,也就造成无法完成垃圾回收,所以主流的虚拟机都没有采用这种算法

  • JVM的垃圾回收算法一起来看看

    目录 垃圾回收算法 概念 1.标记算法 1.1引用计数法(ReferenceCounting) 1.2可达性分析算法(ReachableAnalysis) 2.回收算法 2.1标记清除算法(MarkSweep) 2.2复制算法(Copying) 2.3标记压缩算法(Mark-Compact) 2.4分代回收算法 总结 垃圾回收算法 概念 垃圾回收(Garbage Collection,GC).程序的运行需要资源,无效的对象如果不及时清理就会一直占用资源,所以对内存资源管理就变得十分重要.而Jav

  • JVM分配和回收堆外内存的方式与注意点

    目录 JVM内存模型 如何分配堆外内存 第一种方式:ByteBuffer#allocateDirect 第二种方式:Unsafe#allocateMemory 如何回收堆外内存 第一种方式:Unsafe#freeMemory 第二种方式:JVM回收堆外内存 注意点 注意点1: 注意点2: 引用 总结 JVM内存模型 在JVM中内存被分成两大块,分别是堆内存和堆外内存,堆内存就是JVM使用的内存,而堆外内存就是非JVM使用的内存,一般是分配给机器使用的内存. 那么整个内存模型如下: 因此在JVM中

  • 关于JVM翻越内存管理的墙

    目录 JVM运行时数据区域 程序计数器 Java虚拟机栈 栈桢 本地方法栈 Java堆 分配缓冲区TLAB(Thread Local Allocation Buffer) Java堆的大小设定 方法区 运行时常量池 小结 JVM垃圾回收机制 判断对象存活 引用计数算法 可达性分析算法 几种引用方式 垃圾回收算法 标记清除算法 标记复制算法 标记整理法 分代收集算法 内存回收策略 1.新生代的分配和回收 2.大对象直接进入老年代 3.长期存活的对象将进入老年代 参考 对于Java程序员来说,在虚拟

  • 图文详解java内存回收机制

    在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正因为内存管理完全由JVM负责,所以也使Java很多程序员不再关心内存分配,导致很多程序低效,耗内存.因此就有了Java程序员到最后应该去了解JVM,才能写出更高效,充分利用有限的内存的程序. 1.Java在内存中的状态  首先我们先写一个代码为例子: Person.java package test

  • 老生常谈JVM的内存溢出说明及参数调整

    对于JVM的内存写过的文章已经有点多了,而且有点烂了,不过说那么多大多数在解决OOM的情况,于此,本文就只阐述这个内容,携带一些分析和理解和部分扩展内容,也就是JVM宕机中的一些问题,OK,下面说下OOM的常见情况: 第一类内存溢出,也是大家认为最多,第一反应认为是的内存溢出,就是堆栈溢出: 那什么样的情况就是堆栈溢出呢?当你看到下面的关键字的时候它就是堆栈溢出了: java.lang.OutOfMemoryError: ......java heap space..... 也就是当你看到hea

  • jvm调优的几种场景(小结)

    目录 一.cpu占用过高 (1)用top命令查看cpu占用情况 (2)用top -Hp命令查看线程的情况 (3)把线程号转换为16进制 (4)用jstack工具查看线程栈情况 二.死锁 三.内存泄漏 四.总结 假定你已经了解了运行时的数据区域和常用的垃圾回收算法,也了解了Hotspot支持的垃圾回收器. 一.cpu占用过高 cpu占用过高要分情况讨论,是不是业务上在搞活动,突然有大批的流量进来,而且活动结束后cpu占用率就下降了,如果是这种情况其实可以不用太关心,因为请求越多,需要处理的线程数越

  • 深入理解JVM自动内存管理

    目录 一.前言 1.1 计算机==>操作系统==>JVM 1.1.1 虚拟与实体(对上图的结构层次分析) 1.1.2 Java程序执行(对上图的箭头流程分析) 二.JVM内存空间与参数设置 2.1 运行时数据区 2.2 关于StackOverflowError和OutOfMemoryError 2.2.1 StackOverflowError 2.2.2 OutOfMemoryError 2.3 JVM堆内存和非堆内存 2.3.1 堆内存和非堆内存 2.3.2 JVM堆内部构型(新生代和老年代

  • redis 过期策略及内存回收机制解析

    目录 1. 过期策略 1.1 过期的 key 集合 1.2 定时扫描策略 1.3 从库的过期策略 2. 懒惰删除 2.1 异步线程 2.2 flush 2.3 异步队列 2.4 AOF Sync很慢的问题 2.5 更多异步删除点 3. 过期淘汰配置 4. LRU 算法 4.1 近似 LRU 算法 5. LRU 5.1 LRU 模式 5.2 LFU 模式 redis作为缓存的场景下,内存淘汰策略决定的redis的内存使用效率.考虑到这个很多大厂给出的"送分题",但一般人很少能讲清楚,除非

随机推荐