JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这里仅简单做个笔记,主要参考《深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)》

目前java的jdk默认虚拟机为HotSpot,因此本文涉及虚拟机相关内容都指HotSpot虚拟机

本文主要关注GC的回收:判断哪些对象可回收,如何回收,回收机制

判断哪些对象可回收

GC是通过对象是否存活来决定是否进行回收,判断对象是否存活主要有两种算法:引用计数算法、可达性分析算法

  • 引用计数算法
    引用计数的算法原理是给对象添加一个引用计数器,每被引用一次计数器加1,引用失效时减1,当计数器0后表示对象不在被引用,可以被回收了,引用计数法简单高效,但是存在对象之间循环引用问题,可能导致无法被GC回收,需要花很大精力去解决循环引用问题
  • 可达性分析算法
    可达性分析的算法原理是从对象根引用(堆栈、方法表的静态引用和常量引用区、本地方法栈)开始遍历搜索所有可到达对象,形成一个引用链,遍历的同时标记出可达对象和不可达对象,不可达对象表示没有任何引用存在,可以被GC回收

如何回收

  找到可回收对象后,如何进行回收呢?

  内存回收算法主要有标记-清除、停止-复制、标记-整理,不同算法使用不同的场景,总体来说停止-复制算法适合对象存活时间短,存活率低的新生代,标记-清除和标记-整理算法适合对象存活时间长,存活率高的老年代

  • 标记-清除(Mark-Sweep)
    通过可达性分析算法标记所有不可达对象,然后清理不可达对象。这种算法会形成大量的内存碎片
  • 停止-复制(Stop-Copy)
    将新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复,当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代(这时我们可能回想,若是老年代也满了咋办,若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收,若是内存还不够呢。。。,还不够那不废话了吗,OutOfMemory,不陌生吧哈哈)。从停止-复制算法的原理上我们可以看到,这种算法对于存活率较低的对象回收有着非常高的效率,而且不会形成内存碎片,但是会浪费一定的内存空间,适合对象存活率较低的新生代使用,如果在对象存活率较高的老年代采用这种算法,那将会是一场灾难
  • 标记-整理(Mark-Compact)
    通过可达性分析算法标记所有不可达对象,然后将存活对象都向一个方向移动,然后清理掉边界外的内存。这种算法是将存活对象向着一个方向聚集,然后将剩余区域清空,这种算法适合对象存活率较高的老年代

GC回收机制:分代收集算法

JVM内存收集算法基本上都是采用分代收集算法,即将内存划分为新生代、老年代,也有人把方法区算做永久代

  • 新生代
    对象被创建时,内存分配都是发生在新生代(大对象直接分配在老年代),绝大多数对象都是朝生夕灭,创建后很快就会不在使用,变为不可达的对象,被GC回收掉。新生代的对象存活率很低(到底有多低?研究表明有高达98%的对象创建后很快就消亡,想象一下平时编程,除了全局变量,局部变量在退出调用方法后还有几个能存活),存活时间都很短,新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)
  • 老年代
    当对象在新生代发生了多次Minor GC后仍然存活的对象即进入老年代,老年代的对象比新生多很多,当然了内存比新生代也大很多(大概比例是1:2,即新生代占用堆内存总量的1/3),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高

一般来说我们所说的GC都是发生在新生代和老年代,新生代对象存活时间短,存活率低一般采用停止-复制算法,老年代对象存活时间长,存活率高,一般采用标记-整理、标记-清楚算法,具体采用何种算法和具体采用的垃圾收集器有关

GC里面有些类似未成年人和成年人,新创建的对象为新生代,新生代想要成为老年代需要经过一定的成长(总得一点点长大是吧),新创建的对象年龄为1,每发生一次Minor GC,存活对象的年龄增加1,当经历了15次Minor GC后,仍然存活的对象达到15岁,成达到法定成年年龄15岁(默认是15),正式成为成年人(老年代),对象成年后也就没有了年龄概念,直到对象死亡,会一直呆在老年代,当然也有一些老不死的(静态变量、常量等),会与世长存,除非地球灭亡(GC崩溃)

GC收集器

GC采用分代回收算好后,起着重要作用的是GC收集器,GC收集器分为新生代收集器和老年代收集器,不同的收集器使用不同的收集算法,有着不同的特点,由于目前的收集器在内存回收时无法消除(Stop-the-world),即在回收内存时不可避免的停止用户线程,目前的收集器只能使停顿时间越来越短,但是无法彻底消除,主要的收集其中Parallel Scavenge和Parallel Old是追求吞吐量为目标,其它的收集器都是追求高响应,低停顿,

  新生代收集器:Serial、PraNew、Parallel Scavenge

  老年代收集器:Serial Old、Parallel Old、CMS

  • Serial收集器(复制算法)
    新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
  • Serial Old收集器(标记-整理算法)
    老年代单线程收集器,Serial收集器的老年代版本。
  • ParNew收集器(停止-复制算法)
    新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
  • Parallel Scavenge收集器(停止-复制算法)
    并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。
  • Parallel Old收集器(停止-复制算法)
    Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先
  • CMS(Concurrent Mark Sweep)收集器(标记-清理算法)
    高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择
  • G1(Garbage-First)收集器(标记-整理算法、停止复制算法)
    GC最新型号,高富帅,高并发、可预测停顿、分代收集,不出意外未来主流将会逐步替代CMS,g1模糊了分代概念,虽然还是分为新生代和老年代,但是新生代和老年代不再是物理隔离,而是将内存分为n个region,以region为清理单位,整体采用标记-整理算法,region内部使用停止-复制算法。

JVM内存回收机制简述的更多相关文章

  1. JVM内存回收机制

    1. JVM内存回收机制简述 http://www.cnblogs.com/lzrabbit/p/3826738.html

  2. JVM内存回收机制——哪些内存需要被回收(JVM学习系列2)

    上一篇文章中讨论了Java内存运行时的各个区域,其中程序计数器.虚拟机栈.本地方法栈随线程生灭,且创建时需要多少内存,基本上在译期间就决定的了,所以在内存回收时无需特殊的关注.而堆和方法区则不同,首先 ...

  3. Java jvm 内存回收机制

    http://blog.csdn.net/yaerfeng/article/details/51291903 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方 ...

  4. 深入理解JVM内存回收机制(不包含垃圾收集器)

    目录 垃圾回收发生的区域 如何判断对象是否可以被回收 HotSpot实现 垃圾回收算法 JVM中使用的垃圾收集算法 GC的分类 总结 参考资料 垃圾回收发生的区域 堆是java创建对象的区域(Stri ...

  5. Java技术专题之JVM逻辑内存回收机制研究图解版

    一.引言 JVM虚拟机内存回收机曾迷惑了不少人,文本从JVM实现机制的角度揭示JVM内存回收的原理和机制. 一.Java平台逻辑架构 二.JVM物理结构 通过从JVM物理结构图我们可以看到: 1.JV ...

  6. Java进阶3. 内存回收机制

    Java进阶3. 内存回收机制 20131029 前言: 学过C++的都知道,C++中内存需要程序员自己维护.说道这里,很多开发的同学就感觉很痛苦,当他转向Java的时候,就会说你看Java多好啊,程 ...

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

    JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...

  8. JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代

    内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...

  9. JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)

    一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...

随机推荐

  1. ASP.net MVC中页面跳转

    @Html.ActionLink("Home Name", "Index", "Home")Home name 是 跳转链接的名Index  ...

  2. LINQ - 在Where條件式中使用in與not in

    希望对大家在以后的项目中能用到,我也是在项目中碰到了这个问题: 算算時間,接觸LINQ也有一個月的時間了,可以算是落伍兼新生,不過最近在寫專案的時候,遇到了在LINQ的Where條件式中要如何使用in ...

  3. 大前端学习笔记整理【七】HTTP协议以及http与https的区别

    前言 还是老样子,新博客开始前总是想先啰嗦几句...HTTP协议其实在当初学习java时老师就有提过...但是...反正就那么过去了... 这段时间公司的项目正好要求做https的转换和迁移,然后自己 ...

  4. SQL Server 大数据量分页建议方案

    简单的说就是这个 select top(20) * from( select *, rowid = row_number() over(order by xxx) from tb with(noloc ...

  5. VS与ultraedit 正则表达式替换

    ASP中把request("{param}")调用替换为requestX("{param}") VS 表达式替换(?<a>request\(&quo ...

  6. scrollHeight、scrollTop等的比较

    自接触js以来一直使用的是jquery插件,对js的了解甚少,经常容易混淆element.scrollHeight.element.scrollTop等方法.今天对这些方法做出比较. scrollTo ...

  7. monodevelop 突然莫名其妙的将 warning 全部标记为 error

    这是一个关于 monodevelop 的“坑” 我们在用 monodevelop 编译游戏脚本时, 通常会有一些警告,一般这些警告都是无害的, 不影响游戏运行.可是突然有一天, monodevelop ...

  8. [Leetcode][JAVA] Interleaving String

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  9. 剑指offer算法_位运算求和

    不用+,-,*,/运算求和,可以分成三步: 1.计算两个数字的异或值,相当于只计算每一位的和,不计算进位,得出结果sum: 2.计算两个数字的与值,相当于求出两个数字的进位,然后左移一位,相当于进位, ...

  10. proxyd.c

    /**************************************************************************** * program: proxyd * mo ...