53.垃圾回收算法的实现原理
53.1.目录
53.2.启动Java垃圾回收
53.3.Java垃圾回收过程
53.4.垃圾回收中实例的终结
53.5.对象什么时候符合垃圾回收的条件?
53.5.1.GC Scope 示例程序
53.5.2.GC OutOfMemoryError 的示例程序。

53.垃圾回收算法的实现原理

http://www.importnew.com/13493.html

53.1.目录

1.垃圾回收介绍
2.垃圾回收是如何工作的?
3.垃圾回收的类别
4.垃圾回收监视和分析

本教程是为了理解基本的Java垃圾回收以及它是如何工作的。这是垃圾回收教程系列的第二部分。希望你已经读过了第一部分:《Java 垃圾回收介绍》。
Java 垃圾回收是一项自动化的过程,用来管理程序所使用的运行时内存。通过这一自动化过程,JVM 解除了程序员在程序中分配和释放内存资源的开销。

53.2.启动Java垃圾回收

作为一个自动的过程,程序员不需要在代码中显示地启动垃圾回收过程。System.gc()和Runtime.gc()用来请求JVM启动垃圾回收。
虽然这个请求机制提供给程序员一个启动 GC 过程的机会,但是启动由 JVM负责。JVM可以拒绝这个请求,所以并不保证这些调用都将执行垃圾回收。启动时机的选择由JVM决定,并且取决于堆内存中Eden区是否可用。JVM将这个选择留给了Java规范的实现,不同实现具体使用的算法不尽相同。
毋庸置疑,我们知道垃圾回收过程是不能被强制执行的。我刚刚发现了一个调用System.gc()有意义的场景。通过这篇文章了解一下适合调用System.gc() 这种极端情况。

53.3.Java垃圾回收过程

垃圾回收是一种回收无用内存空间并使其对未来实例可用的过程。

Eden 区:当一个实例被创建了,首先会被存储在堆内存年轻代的 Eden 区中。
注意:如果你不能理解这些词汇,我建议你阅读这篇 垃圾回收介绍 ,这篇教程详细地介绍了内存模型、JVM 架构以及这些术语。
Survivor 区(S0 和 S1):作为年轻代 GC(Minor GC)周期的一部分,存活的对象(仍然被引用的)从 Eden 区被移动到 Survivor 区的 S0 中。类似的,垃圾回收器会扫描 S0 然后将存活的实例移动到 S1 中。
(译注:此处不应该是Eden和S0中存活的都移到S1么,为什么会先移到S0再从S0移到S1?)
死亡的实例(不再被引用)被标记为垃圾回收。根据垃圾回收器(有四种常用的垃圾回收器,将在下一教程中介绍它们)选择的不同,要么被标记的实例都会不停地从内存中移除,要么回收过程会在一个单独的进程中完成。
老年代: 老年代(Old or tenured generation)是堆内存中的第二块逻辑区。当垃圾回收器执行Minor GC周期时,在S1 Survivor区中的存活实例将会被晋升到老年代,而未被引用的对象被标记为回收。
老年代 GC(Major GC):相对于Java垃圾回收过程,老年代是实例生命周期的最后阶段。Major GC 扫描老年代的垃圾回收过程。如果实例不再被引用,那么它们会被标记为回收,否则它们会继续留在老年代中。
内存碎片:一旦实例从堆内存中被删除,其位置就会变空并且可用于未来实例的分配。这些空出的空间将会使整个内存区域碎片化。为了实例的快速分配,需要进行碎片整理。基于垃圾回收器的不同选择,回收的内存区域要么被不停地被整理,要么在一个单独的GC进程中完成。

53.4.垃圾回收中实例的终结

在释放一个实例和回收内存空间之前,Java 垃圾回收器会调用实例各自的 finalize() 方法,从而该实例有机会释放所持有的资源。虽然可以保证 finalize() 会在回收内存空间之前被调用,但是没有指定的顺序和时间。多个实例间的顺序是无法被预知,甚至可能会并行发生。程序不应该预先调整实例之间的顺序并使用 finalize() 方法回收资源。
任何在 finalize过程中未被捕获的异常会自动被忽略,然后该实例的 finalize 过程被取消。
JVM 规范中并没有讨论关于弱引用的垃圾回收机制,也没有很明确的要求。具体的实现都由实现方决定。
垃圾回收是由一个守护线程完成的。

53.5.对象什么时候符合垃圾回收的条件?

所有实例都没有活动线程访问。
没有被其他任何实例访问的循环引用实例。

Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。

引用类型 垃圾收集
强引用(Strong Reference) 不符合垃圾收集
软引用(Soft Reference) 垃圾收集可能会执行,但会作为最后的选择
弱引用(Weak Reference) 符合垃圾收集
虚引用(Phantom Reference) 符合垃圾收集

在编译过程中作为一种优化技术,Java编译器能选择给实例赋 null 值,从而标记实例为可回收。

class Animal {public static void main(String[] args) {Animal lion = new Animal();System.out.println("Main is completed.");}protected void finalize() {System.out.println("Rest in Peace!");}
}

在上面的类中,lion 对象在实例化行后从未被使用过。因此 Java 编译器作为一种优化措施可以直接在实例化行后赋值lion = null。因此,即使在 SOP 输出之前, finalize 函数也能够打印出 ‘Rest in Peace!’。我们不能证明这确定会发生,因为它依赖JVM的实现方式和运行时使用的内存。然而,我们还能学习到一点:如果编译器看到该实例在未来再也不会被引用,能够选择并提早释放实例空间。
关于对象什么时候符合垃圾回收有一个更好的例子。实例的所有属性能被存储在寄存器中,随后寄存器将被访问并读取内容。无一例外,这些值将被写回到实例中。虽然这些值在将来能被使用,这个实例仍然能被标记为符合垃圾回收。这是一个很经典的例子,不是吗?
当被赋值为null时,这是很简单的一个符合垃圾回收的示例。当然,复杂的情况可以像上面的几点。这是由 JVM 实现者所做的选择。目的是留下尽可能小的内存占用,加快响应速度,提高吞吐量。为了实现这一目标, JVM 的实现者可以选择一个更好的方案或算法在垃圾回收过程中回收内存空间。
当 finalize() 方法被调用时,JVM 会释放该线程上的所有同步锁。

53.5.1.GC Scope 示例程序

Class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// No Object Is Eligible for GCt1.t = t2; // No Object Is Eligible for GCt2.t = t3; // No Object Is Eligible for GCt3.t = t1; // No Object Is Eligible for GCt1 = null;// No Object Is Eligible for GC (t3.t still has a reference to t1)t2 = null;// No Object Is Eligible for GC (t3.t.t still has a reference to t2)t3 = null;// All the 3 Object Is Eligible for GC (None of them have a reference.// only the variable t of the objects are referring each other in a// rounded fashion forming the Island of objects with out any external// reference)}protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// 没有对象符合GCt1.t = t2; // 没有对象符合GCt2.t = t3; // 没有对象符合GCt3.t = t1; // 没有对象符合GCt1 = null;// 没有对象符合GC (t3.t 仍然有一个到 t1 的引用)t2 = null;// 没有对象符合GC (t3.t.t 仍然有一个到 t2 的引用)t3 = null;// 所有三个对象都符合GC (它们中没有一个拥有引用。// 只有各对象的变量 t 还指向了彼此,// 形成了一个由对象组成的环形的岛,而没有任何外部的引用。)}protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}

53.5.2.GC OutOfMemoryError 的示例程序

GC并不保证内存溢出问题的安全性,粗心写下的代码会导致 OutOfMemoryError。

import java.util.LinkedList;
import java.util.List;public class GC {public static void main(String[] main) {List l = new LinkedList();// Enter infinite loop which will add a String to the list: l on each// iteration.do {l.add(new String("Hello, World"));} while (true);}
}

输出:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.LinkedList.linkLast(LinkedList.java:142)at java.util.LinkedList.add(LinkedList.java:338)at com.javapapers.java.GCScope.main(GCScope.java:12)

接下来是垃圾收集系列教程的第三部分,我们将会看到常用的 不同 的Java垃圾收集器。

53.垃圾回收算法的实现原理、启动Java垃圾回收、Java垃圾回收过程、垃圾回收中实例的终结、对象什么时候符合垃圾回收的条件、GC Scope 示例程序、GC OutOfMemoryError的示例相关推荐

  1. 垃圾回收算法的实现原理_有关垃圾回收算法工作原理的动画指南

    垃圾回收算法的实现原理 Garbage Collection is the process of cleaning up a computer's memory by getting rid of d ...

  2. 【分布式ID】理解Snowflake算法的实现原理

    1.概述 转载:冷饭新炒:理解Snowflake算法的实现原理 我上次也看了一个视频讲解:[分布式ID]键高并发 分布式 全局唯一 ID 雪花算法 snowflake 2.前提# Snowflake( ...

  3. 几种随机算法的实现原理

    在日常工作中,经常需要使用随机算法.比如面对大量的数据, 需要从其中随机选取一些数据来做分析. 又如在得到某个分数后, 为了增加随机性, 需要在该分数的基础上, 添加一个扰动, 并使该扰动服从特定的概 ...

  4. 冒泡算法的实现原理:(从小到大排序)

    冒泡算法的实现原理:(从小到大排序) 1:比较相邻的两个元素,如果第一个比第二个大就交换位置 2:对每一对相邻的元素进行比较,从开始第一对到结尾的最后一对,这样最后的元素就是最大的了 3:每一次这样循 ...

  5. MD5算法的实现原理

    [项目]磁盘文件管理工具 项目预期目标 本项目旨在实现一个文件管理项目,主要功能为删除磁盘中的重复文件(拟采用计算机文件指纹的方法来判断两个文件是否相同,所谓的文件指纹就是数字签名) 常用的数字签名算 ...

  6. java用循环给map里面存值_Java中如何遍历Map对象的4种方法

    方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. 1 Map map = new HashMap();2 3 for ...

  7. java内部类外部类_Java内部类:如何在内部类中返回外部类对象

    Nasted Class 的介绍,请详见参考 今天讨论的不是不是内部类的概念,而是具体使用的一个场景-如何在内部类中返回外部对象 (孤猪:我在程序里也碰到过一次这样的状况,非静态内部类可以直接调用外部 ...

  8. 4. GC 算法(实现篇) - GC参考手册

    您应该已经阅读了前面的章节: 垃圾收集简介 - GC参考手册 Java中的垃圾收集 - GC参考手册 GC 算法(基础篇) - GC参考手册 学习了GC算法的相关概念之后, 我们将介绍在JVM中这些算 ...

  9. 游戏中常用的寻路算法的分享(3):A*算法的实现

    概述 剥除代码,A* 算法非常简单.算法维护两个集合:OPEN 集和 CLOSED 集.OPEN 集包含待检测节点.初始状态,OPEN集仅包含一个元素:开始位置.CLOSED集包含已检测节点.初始状态 ...

最新文章

  1. R语言使用fs包的dir_delete函数删除指定的文件目录(remove the directory)、举一反三、file_delete函数、link_delete函数可以用来删除文件和文件夹
  2. (面试)java基础-== 和 equals 的区别?
  3. java线程如何避免死锁_Java面试问题,如何避免Java线程中的死锁?
  4. php ie 下载 乱码,php ie下载文件名乱码怎么办
  5. 交换机putty怎么调试_使用在300和500系列托管型交换机的一个控制台连接通过PuTTY访问CLI...
  6. 计算机专业英语第07章,计算机专业英语 -第7章1.ppt
  7. php properties,PHP ReflectionClass getStaticProperties()用法及代码示例
  8. 矩阵、优化理论常用记号
  9. 如何打破产品的创新窘境
  10. 操作系统指纹识别(基于kali)
  11. avr单片机动态数码管c语言,AVR单片机8位数码管显示的程序实现(两种方法介绍)...
  12. Java成员方法getinfo_Java Swagger.getInfo方法代码示例
  13. 2019春实习-百度-计算机视觉算法研发工程师真题
  14. 产品申请UL标志包括以下几个步骤
  15. 2020年书法落款_书法落款的基本常识最新版
  16. 7-15 福到了 c语言,7-7 福到了 (15分)
  17. html+css3跑马灯(抖音我们的照片记录幸福到永远)
  18. android资源收藏
  19. 历代Android开机动画,回顾Windows历代版本开机画面:XP最经典
  20. 前端的岗位以及初步了解

热门文章

  1. apollo 配置中心_Apollo配置中心搭建笔记
  2. python numpy库中省略号...的一些用法
  3. 基础知识:数字、字符串、列表 的类型及内置方法
  4. Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)
  5. 史上最全 Python Re 模块讲解(一)
  6. VTK:参数化超椭球用法实战
  7. OpenCASCADE:网格
  8. MRU 列表序列化的 Boost.MultiIndex 示例
  9. GDCM:gdcm::StringFilter的测试程序
  10. no exceptions support的测试程序