垃圾回收需要解决的问题

谁需要被回收

什么时候回收

怎么回收

谁需要被回收

如果一个对象再也不会被用到,就可以回收它了,所以关键在于如何知道一个对象再也不被使用了。

引用计数

当一个对象被引用时,引用计数加1,当引用失效时,计数减1。简单直观,但会出现循环引用问题。

a.tb = b

b.ta = a

即使 a 和 b 再也不会被用到了,但他们之间互相引用,导致引用计数一直不为0,无法被回收。

可达性分析

Java, C# 的主流实现都是使用可达性分析来判断一个对象是否存活的。如果从 GC Root 可以到达一个对象,那么 这个对象是可达的,还存活着,否则就不存活,可以被回收。 GC

Root 包含以下几类。

虚拟机栈引用的对象

方法区静态属性引用的对象

方法区中常量引用的对象

本地方法栈中JNI引用的对象

何时及如何回收

何时及如何回收,涉及具体的回收策略,就放一起说了。

标记回收算法

最基本的垃圾回收算法,第一次扫描,标记所有可以被回收的对象,第二次扫描,回收被标记的对象。

不足之处

效率低

会产生内存碎片

复制算法

复制算法将内存分成两部分,每次只使用两部分。假如当前使用的是左半块,右半块没使用。现在要垃圾回收了, 就将左半块还存活的对象复制到右半块。然后将左半块一次性全部回收。

好处是

高效

没内存碎片

坏处是

空间效率低,有半块都不能用

解决方法是,调整左右两块的比例。在 HotSpot 中,内存分成一块 Eden,两块 Survivor,比例是 8:1. 每次使用一块 Eden, 一块 Survivor A, 另一块 Survivor B 备用。 垃圾回收时,将 Eden 和 Survivor

A 上存活的对象复制到 Survivor B 上,然后将 Eden 和 Survivor A 回收。然后下次使用 Eden, Survivor B, 而 Survivor A 这次备用。

这种方法的前提是每次回收时,大量对象都死掉了,只有一小部分存活着,这样,只复制一小部分就好。但是,如果大量对象存活时间比较长,就要反复来回复制,简直浪费生命。从这一点也可以看出,要根据对象存活时间的特点使用不同的回收策略。

标记整理算法

标记整理算法是对标记清除算法的改进。第一次扫描标记需要回收的对象。第二次不是将这些对象清除,而是将还存活的对象移动到内存区域的一端,全他们连在一起。然后对这块区域边界以外的地方全部回收。

分代收集算法

从上面的讨论可以看出,要根据对象存活时间使用不同回收策略。有些对象存活时间比较短,这样每次回收时,存活对象少,可以使用复制算法。而有些对象存活时间比较长,这样每次回收时,需要回收的对象少,可以使用标记清除和标记整理算法。Java 堆据此分为新生代和老年代,新生代中对象存活时间短,老年代中对象存活时间长。

分代的标准有两个,一个是存活时间,一个是对象大小,大对象会直接进入老年代。

HotSpot

垃圾回收器

HotSpot 垃圾回收器按分代,可以分为新生代回收器和老年代回收器。按垃圾回收器线程数可以分为单线程回收器和多线程回收器。按垃圾回收时是否需要停止所有工作线程可以分为并发回收器和非并发回收器。所以,看到一个回收器,需要明白它:

用于新生代还是老年代

单线程还是多线程

工作时是否需要停止所有工作线程

Serial

回收器

Client 模式下默认新生代回收器,采用复制算法

单线程

需要暂停所有工作线程

ParNew

回收器

Server 模式下首选新生代回收器,采用复制算法

多线程

不需暂停所有工作线程

只有它可与 CMS 回收器配合使用

Parallel

Scavenge 回收器

新生代回收器,采用复制算法

多线程

目标在于达到一个可控的吞吐量(吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾回收时间))

其它回收器目标在于减少用户程序因为垃圾回收而停顿的时间,而Parallel Scavenge 回收器 的目标在于可按的吞吐量,因为它又被称为吞吐量优先回收器。 这里有一个矛盾,如果每次停顿时间减少,那么用户程序可以得到更快的响应,但这同 时意味着,垃圾回收变得频繁,垃圾回收总体时间变长,吞吐量下降。可以使用 -XX:MaxGCPauseMillis 调整垃圾回收停顿时间,也可以使用 -XX:GCTimeRation 调整吞吐量。

Serial

Old 回收器

老年代回收器,采用标记整理算法

单线程

需要暂停所有工作线程

Client 模式下使用

Serial 回收器老年代版本

Parallel

Old 收集器

老年代回收器,采用标记整理算法

多线程

Parallel Scavenge 老年代版本

CMS(Concurrent

Mark Sweep) 回收器

老年代回收器,采用标记清除算法

多线程

总体上,不需要暂停所有工作线程

运行过程:

初始标记

并发标记

重新标记

并发清除

其中并发标记和重新标记需要暂停所有用户线程,但这两个阶段用时相对另外两个阶段非常少。而并发标记与并发清除消耗时间长,但他们可以与 用户线程一起工作。

初始标记只标记 GC Root 直接关联的对象,重新标记修正并发标记期间因用户程序运行导致标记变动的对象。

G1(Garbage-First)

回收器

新生代与老年代不再物理隔离,打破原有分代概念

多线程

不需要暂停所有工作线程

不需要与其它回收器配合使用

整体上标记整理算法,局部是复制算法,不会产生内存碎片

可以预测停顿,这意味着用户可以指定回收操作在多长时间内完成

这篇文章是学习《深入理解Java虚拟机》的总结。

原文:http://blog.csdn.net/on_1y/article/details/38900597

java回收策略_Java 中的垃圾回收策略相关推荐

  1. 简述python垃圾回收机制_python中的垃圾回收机制简述

    2020年12月5日21:47:35 王凯玉 python中的垃圾回收机制 引用计数 # 引用计数 引用计数是编程语言中的一中内存管理技术,可以将资源的被引用次数保存起来. 当引用计数为0时,资源将被 ...

  2. java String如何回收_java中的垃圾回收

    原文-http://blog.csdn.net/zsuguangh/article/details/6429592 1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确 ...

  3. java年轻代_Java分代垃圾回收机制:年轻代/年老代/持久代(转)

    虚拟机中的共划分为三个代:年轻代(Young Generation).年老点(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...

  4. java清空字符串_java面向对象,垃圾回收机制

    一.类的属性 属性用于定义该类或该类对象包含的数据或者说静态特征.属性作用范围是整个类体. 在定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的值对其初始化. 二.UML图 三.类和对 ...

  5. 编程基础 垃圾回收_编程中的垃圾回收指南

    编程基础 垃圾回收 什么是垃圾回收? (What is Garbage Collection?) In general layman's terms, Garbage collection (GC) ...

  6. 关于python的垃圾回收机制_Python中的垃圾回收机制

    GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...

  7. java 垃圾回收 指针_Java 和 C++ 垃圾回收之间的差别

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1.指针 JAVA语言让编程者无法找到指针来直接访问内存无指针,并且增添了自动的内存管理功能,从而有效地防止了c/c++语言中指针操作失误,如野指针所造成 ...

  8. java gc回收机制_Java中的GC回收机制

    为什么要进行GC回收? 当我们新建一个对象时,系统就会为其分配一定的内存空间,而有时候新建的对象没有去使用时,不回收的话会极大浪费内存空间,造成系统效率低下. 什么时候进行GC回收? 1.当CPU空闲 ...

  9. 【java虚拟机序列】java中的垃圾回收与内存分配策略

    在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...

最新文章

  1. Exchange与ADFS单点登录 PART 2:部署和配置ADFS
  2. 单片机ad转换测电压c语言,大家帮我看下这个STC AD转换 测电压程序错在哪里,谢谢了...
  3. php static 和 global,php中global static和$GLOBALS使用与区别
  4. 移动互联网下半场,iOS开发者如何“高薪”成长?
  5. 用VBA得到EXCEL表格中的行数和列数
  6. python netifaces模块 获取本机IP,网关等信息
  7. Debian Linux下的Python学习——列表,元组和字典之列表
  8. 华为交换机S5700系列配置通过STelnet登录设备示例
  9. linux 终端 收取邮件,linux mail 命令 (收发邮件)
  10. 答非所问:产品质量怎样?发现了很多BUG
  11. window xp共享文件夹
  12. Another version of Vue Devtools seems to be installed报错
  13. 阿里云ECS服务器常用入门配置命令
  14. Maven报错Original error: Could not transfer artifact
  15. 常用的数据集成ETL工具有哪些?
  16. 电子电路中的各种接地(接地保护与GND)
  17. 国内专利申请相关概念综述
  18. 山东职业学院的计算机网络技术,2017年山东信息职业技术学院计算机网络技术教学质量...
  19. win7远程桌面需要开启哪些服务器,win7系统如何开启远程桌面_网站服务器运行维护...
  20. GoPro fusion(双目) Vr视频如何导出至手机和PC端(Win)

热门文章

  1. android手机更改手机密码,手机忘记密码如可解决 安卓手机重置密码教程【详解】...
  2. Java 数据类型(基本数据类型、引用数据类型)
  3. 质数检验(埃拉托色筛选法、根号x复杂度算法)
  4. 120个微信小程序源码,打包下载
  5. FPGA芯片的GTX/GTH/GTY/GTP/GTZ/GTM高速信号有什么区别?
  6. 菜鸟学Java——简单验证码生成(Java版)
  7. Java之Builder模式
  8. 游戏中的显示器选项的acm
  9. Java的字符串连接符(+)
  10. 阿里亮相 SIGCOMM2017 调度系统NetO惊艳全场