Java基础教程:垃圾回收

垃圾回收

  垃圾回收(Garbage Collection,GC),顾名思义是释放垃圾占用的空间,防止内存泄漏。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收

  认定垃圾时有两种主要算法:引用计数法、可达性分析算法。

引用计数法

  引用计数法(Reachability Counting)是通过在对象头中分配一个空间来记录该对象被引用的次数(Reference Count)。如果该对象被其他对象引用,则它的引用计数就加一,如果一个删除对该对象的引用,那么他的引用计数就减,当一个对象的引用计数为0时,那么该对象就会被回收

  如String m = new String("jack"),jack字符串有一个引用,就是m:

   

  将m设置为null,这时候jack的引用次数为0,意味着这块内容要被回收了。

  

  但是引用计数法无法解决循环依赖问题,比如 a.value = b;b.value =a ;这样相会引用,导致它们永远不会被回收。

可达性分析算法

  可达性分析算法(Reachability Analysis)的基本思路是,通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时(即从 GC Roots 节点到该节点不可达),则证明该对象是不可用的

  

  通过可达性分析算法,成功解决了引用计数无法解决的“循环依赖”问题。只要你无法与 GC Root 建立直接或间接的连接,系统就会判定你为可回收对象。

  在Java语言中,可作为GC Root的对象包括以下四种:

  • 虚拟机栈中引用的对象
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象  

怎么回收垃圾

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

标记清除

  

  标记清除算法(Mark-Sweep),先对即可回收的垃圾进行标记,然后清理掉,就像上图一样,清理掉的垃圾就变成未使用的内存区域,等待被再次使用。逻辑很清晰,但是它存在一个很大的问题,那就是内存碎片。会导致我们想要一个连续的大一点的空间,但是被分散在各个地方,无法申请到。

复制

  

  复制算法(Copying)是在标记清除算法上演化而来,解决标记清除算法的内存碎片问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。保证了内存的连续可用,内存分配时也就不用考虑内存碎片等复杂情况,逻辑清晰,运行高效。

  但是它也有一个问题,就是空间必须拆分,即你有10G内存,但是能分配的最大单个对象只有5G。

标记整理

  

  标记整理算法(Mark-Compact)标记过程仍然与标记 --- 清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,再清理掉端边界以外的内存区域

  它仍然有一个致命问题,就是效率问题,它对内存变动更频繁,需要整理所有存活对象的引用地址,在效率上比复制算法要差很多

分代收集算法

  分代收集算法(Generational Collection)严格来说并不是一种思想或理论,而是融合上述3种基础的算法思想,而产生的针对不同情况所采用不同算法的一套组合拳。对象存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记-清理或者标记整理算法来进行回收

Java堆的结构

  

  Java堆分为两个区域,年轻代和老年代,其中年轻代又分为Eden区和Survivor,Survivor分为Form 和To 两个区。

Eden

  大多数情况下,对象会在新生代Eden区中进行分配,当Eden区没有足够空间进行分配时,虚拟机会发起一次Minor GC,Minor GC相比Major GC更频繁,回收速度也更快。

  通过Minor GC之后,Eden会被清空,Eden区中绝大多数对象会被回收,而那些无需回收的存活对象,就会进入Survivor的Form区,若Form区不够,则直接进入Old区。

Survivor

  Survivor区相当于Eden区与Old区的一个缓存,类似我们交通灯中的黄灯。Survivor区存在的意义就是减少被送到老年区的对象,从而减少Major GC的发生。Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才能被送到老年代。Survivor设置两个的原因是,Survivor内部使用特殊的清理算法(类似于复制算法),可以解决内存碎片化。

Old

  老年代占据着2/3的堆内存空间,只有在Major GC的时候才会进行清理。在老年代,对象存活率很高,如果复制的话很麻烦,采用标记整理算法较好。

特殊情况

  大对象是需要大量连续内存空间的对象,这部分对象直接进入老年代。

参考链接

  • https://mp.weixin.qq.com/s/v7hXr1RHKJpS20LxctvCFg
  • 《深入理解Java虚拟机》。

Java基础教程:垃圾回收的更多相关文章

  1. Java基础教程——垃圾回收机制

    垃圾回收机制 Garbage Collection,GC 垃圾回收是Java的重要功能之一. |--堆内存:垃圾回收机制只回收堆内存中对象,不回收数据库连接.IO等物理资源. |--失去使用价值,即为 ...

  2. java基础之 垃圾回收机制

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...

  3. Java基础之垃圾回收

    /** * 对象在没有任何引用可以到达时,生命周期结束,成为垃圾. * 所有对象在被回收之前都会自动调用finalize()方法. * ******************************** ...

  4. Java基础教程:面向对象编程[1]

    Java基础教程:面向对象编程 内容大纲 Java语言概述 Java语言特点 1.Java为纯面向对象的语言,它能够直接反映现实生活中的对象.总之,Everything is object! 2.平台 ...

  5. Java基础教程:Java内存区域

    Java基础教程:Java内存区域 运行时数据区域 Java虚拟机在执行Java程序的过程种会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟 ...

  6. Java GC(垃圾回收)机制知识总结

    目录 Java GC系列 Java关键术语 Java HotSpot 虚拟机 JVM体系结构 Java堆内存 启动Java垃圾回收 Java垃圾回收过程 垃圾回收中实例的终结 对象什么时候符合垃圾回收 ...

  7. Java编程思想学习笔记_1(Java内存和垃圾回收)

    1.Java中对象的存储数据的地方: 共有五个不同的地方可以存储数据. 1)寄存器.最快,因为位于处理器的内部,寄存器按需求分配,不能直接控制. 2)堆栈.位于通用RAM,通过堆栈指针可以从处理器那里 ...

  8. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  9. JVM基础(5)-垃圾回收机制

    一.对象引用的类型 Java 中的垃圾回收一般是在 Java 堆中进行,因为堆中几乎存放了 Java 中所有的对象实例.谈到 Java 堆中的垃圾回收,自然要谈到引用.在 JDK1.2 之前,Java ...

随机推荐

  1. YAML_03 用playbook安装Apache,修改端口,配置ServerName,修改主页,设置开机自启

    ansible]# vim http.yml --- - hosts: cache   remote_user: root   tasks:     - name: install one speci ...

  2. [分享]Passcape Software - Windows Password Recovery

    [分享]Passcape Software - Windows Password Recovery https://bbs.pediy.com/thread-245965.htm   [[other] ...

  3. codevs1504愚蠢的组合数 / RQNOJ愚蠢的组合数

    1504 愚蠢的组合数  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 最近老师教了狗狗怎么算组合数,狗狗又 ...

  4. C语言实现多线程排序

    #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <string.h& ...

  5. 区块链阶段1-Linux基础- 1 Linux简介

    对于一般的办公和娱乐我们接触更多的是Windows.但是对于IT从业人员,特别是从事服务器管理以及软件开发的人员来讲,我们需要熟练掌握 Linux/UNIX操作系统的知识.所以,Linux 是众多操作 ...

  6. mysql小白入门

    mysql简介 1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅 ...

  7. 三大框架 之 Spring-Aop

    目录 AOP AOP简介 开发存在 的问题 JDK动态代理 cglib动态代理 Spring的AOP简介 AOP相关术语 Joinpoint:连接点 Pointcut:切入点 Advice:通知 In ...

  8. 第06组 Alpha冲刺(2/6)

    队名:拾光组 组长博客链接 作业博客链接 团队项目情况 燃尽图(组内共享) 组长:宋奕 过去两天完成了哪些任务 主要完成了上传照片模块的信息采集 具体完成了采集用户上传的照片信息.分析图像数据.比对数 ...

  9. 2019SDN课程阅读作业(2)

    1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 分为三个阶段,第一个阶段是主动网络(从20世纪90年代中期到21世纪初),它在网络中引入了可编程功能,以实现更大的创新:第二个 ...

  10. csapp网络编程初学笔记

    csapp网络编程初学笔记 客户端-服务器编程模型 每个网络应用都是基于客户端-服务器模型,服务器管理某种资源,并且通过操作来为它的客户提供某种服务 客户端-服务器模型中的基本操作是transacti ...