1,什么样的对象是垃圾

在Java中采用可达性分析的方式来确定对象是否会成为可回收对象。基本思想就是Java会有一系列的“GC Roots” 对象作为起始搜索点,如果没有一条路径能从GC Roots到某个Object,那这个Object就是不可达的,但不可达对象不会立马变为可回收对象,而是经过两次标记过程,如果两次标记过程都仍是不可达的,那就真的是可回收对象了。

比较常见的将对象判定为可回收对象的情况:

a,将某个引用赋值为null,或将某个对象的引用指向另一个对象。

Object obj = newObject();

obj= null;

Object obj1= newObject();

Object obj2= newObject();

obj1= obj2;

b,局部变量指向的对象

for(int i=0;i<3; i++) {

Object o= newObject();

}

每次循环结束后,Object对象就成了可回收对象。

c,弱引用指向的对象

WeakReference wr = new WeakReference(new String("test"));

注意:SoftReference指向的对象会在内存不足的情况下被判定为可回收对象。

垃圾收集算法

在确定了哪些垃圾可以被回收后,垃圾收集器要做的事情就是开始进行垃圾回收,但是这里面涉及到一个问题是:如何高效地进行垃圾回收。由于Java虚拟机规范并没有对如何实现垃圾收集器做出明确的规定,因此各个厂商的虚拟机可以采用不同的方式来实现垃圾收集器,所以在此只讨论几种常见的垃圾收集算法的核心思想。

1.Mark-Sweep(标记-清除)算法

这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。具体过程如下图所示:

从图中可以很容易看出标记-清除算法实现起来比较容易,但是有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。

2.Copying(复制)算法

为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。具体过程如下图所示:

这种算法虽然实现简单,运行高效且不容易产生内存碎片,但是却对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。

很显然,Copying算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么Copying算法的效率将会大大降低。

3.Mark-Compact(标记-整理)算法

为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。具体过程如下图所示:

4.Generational Collection(分代收集)算法

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

对象的内存分配,往大方向上讲就是在堆上分配,对象主要分配在新生代的Eden Space和From Space,少数情况下会直接分配在老年代。如果新生代的Eden Space和From Space的空间不足,则会发起一次GC,如果进行了GC之后,Eden Space和From Space能够容纳该对象就放在Eden Space和From Space。在GC的过程中,会将Eden Space和From  Space中的存活对象移动到To Space,然后将Eden Space和From Space进行清理。如果在清理的过程中,To Space无法足够来存储某个对象,就会将该对象移动到老年代中。在进行了GC之后,使用的便是Eden space和To Space了,下次GC时会将存活对象复制到From Space,如此反复循环。当对象在Survivor区躲过一次GC的话,其对象年龄便会加1,默认情况下,如果对象年龄达到15岁,就会移动到老年代中。

一般来说,大对象会被直接分配到老年代,所谓的大对象是指需要大量连续存储空间的对象,最常见的一种大对象就是大数组,比如:

byte[] data = new byte[4*1024*1024]

这种一般会直接在老年代分配存储空间。

当然分配的规则并不是百分之百固定的,这要取决于当前使用的是哪种垃圾收集器组合和JVM的相关参数。

总结一下:

1,mark-sweep算法简单易实现,但是会产生内存碎片

2,copying算法,将内存分为AB两半,一开始只使用A内存来存放对象,清理时将剩余的对象复制到B,然后把A全部清理,之后就用B来存储新对象,等要执行垃圾回收时再倒腾到A,一直这样重复,这样的缺陷是内存利用率低。

3,mark-compact算法, 先标记出要回收的对象,然后将剩余的对象压紧(compact)堆到一边,然后把剩下的另一边清理掉。

4, Generational Collection(分代收集算法):是目前JVM最常使用的。把堆分为老年代和新生代。新生代使用Copying算法,老年代使用Mark-Compact算法。

java 2分代复制垃圾回收_Java垃圾回收机制相关推荐

  1. java 2分代复制垃圾回收_Java对象的后事处理——垃圾回收(二)

    1 先谈Finalize() finalize()能做的所有工作,使用try-finally或者其他方式都可以做得更好.更及时,所以笔者建议大家完全可以忘掉Java语言中有这个方法的存在. --< ...

  2. 简介三种垃圾回收机制:分代复制垃圾回收,标记垃圾回收,增量垃圾回收

    一.分代复制垃圾回收 不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比 ...

  3. java 终结此段代码并重新运行_Java垃圾回收

    好久没看关于java的书了, 最近, 看了James Gosling的<>, 做了一些读书笔记. 这部分是关于垃圾回收的. 1.垃圾回收 对象是使用new创建的, 但是并没有与之相对应的d ...

  4. java list clear 垃圾回收_java垃圾回收机制

    1.什么是垃圾回收? 程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导数内存溢出,所以内存资源的管是非常重要了. 1.1.C/C++语言的垃圾回收 在C/C+ ...

  5. java 老年代回收_Java垃圾回收之老年代垃圾收集器

    1.Serial Old 收集器(-XX: +UseSerialOldGC, 标记-整理算法) 1.1 单线程收集,进行垃圾收集时,必须暂停所有工作线程 1.2 简单高效,Client模式下默认的老年 ...

  6. java list clear 垃圾回收_Java垃圾回收

    1.标记-清除算法 这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存.这种收集器一般使用单线程工作并停止其他操作. 复制算法 这种收集器将堆栈分为两个域,常称为 ...

  7. java垃圾回收_Java垃圾回收机制

    垃圾回收的意义 如果不进行垃圾回收,内存迟早会被消耗空. 垃圾回收机制的引入可以有效的防止内存泄露.保证内存的有效使用,也减轻了 Java 程序员的对内存管理的工作量. 内存泄露:指该内存空间使用完毕 ...

  8. java如何保证类不被回收_Java垃圾回收机制

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

  9. java 静态数组 垃圾回收_java垃圾回收

    参考文献: 1.垃圾收集算法的核心思想 Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象.该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引 ...

  10. java 强制垃圾回收_Java垃圾回收机制

    Java垃圾回收机制 垃圾回收机制用到finalize.当程序创建对象.数组等引用类型实体时,系统都会在堆内存中为之分配一块内存区,对象就保存在这块内存中,当这块内存不再被任何引用变量引用时,这块内存 ...

最新文章

  1. 如何制定项目工作计划
  2. 网上讨论“电商平台打败了实体店”?
  3. Ural 1001 Reverse Root 解题报告
  4. flink源码分析_源码解析 | 万字长文详解 Flink 中的 CopyOnWriteStateTable
  5. yuki翻译器钩子_最新YUKI GALGAME翻译器下载地址电脑版-CC软件
  6. c语言十进制转二进制过程,C语言十进制转二进制代码实例
  7. java快速开发项目_GitHub - Johnnyzhoutq/X-SpringBoot: X-SpringBoot是一个轻量级的Java快速开发平台,能快速开发项目并交付【接私活利器】...
  8. 阿里巴巴推进中国中产阶级奢侈消费
  9. Unity格子类三消游戏【物体下落】小细节(Unity萌新的备忘录)
  10. 一个故事轻松记忆常见252个英语字根(1~30)
  11. css font-size 失效,css font-size不管用的经解决方法
  12. iOS 第四天之ViewController
  13. python画大对勾_多种方法告诉你!Word如何在方框中打对勾√和叉叉×
  14. 不要过分相信基础函数, 因为那也是人写的------警惕负负得正的现有逻辑之坑
  15. 图像识别流程学习总结
  16. OpenHarmony HDF Input框架模块 按键控制LED基于小熊派micro
  17. 计算机网络笔记4 网络层
  18. form表单数据回填
  19. pygame编写篮球游戏-火柴人运球避开防守跳起投篮
  20. CentOS 8 安装MySQL(各版本完美解决方案)

热门文章

  1. Java 8 新特性:3-函数(Function)接口
  2. BTrace入门教程
  3. 关于C#编译器错误CS0685(VS2005)
  4. c235delc杂合变异遗传吗_血常规正常就真的没有地贫吗?
  5. pandas.iloc, pandas.loc用法
  6. spring5.0学习笔记9
  7. java文件字节流和文件字符流的使用
  8. docker如何进入后台容器
  9. ERROR: CMake must be installed to build dlib
  10. Docker操作命令——查看、停止、删除容器