java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”。jvm解决的两个问题:给对象分配内存以及回收分配给对象的内存。GC:将内存中不再被使用的对象进行回收。GC的作用域是JVM运行时数据区的方法区和堆。频繁收集Young区;较少收集Old区;基本不动Perm区。

1.概述

  垃圾收集(GC)需要完成的3件事:

  (1)哪些内存需要回收?

  (2)什么时候回收?

  (3)如何回收?

  GC类型:

  (1) Minor GC:针对新生代的GC

  (2) Major GC:针对旧生代的GC

  (3) Full GC:针对永久代、新生代、旧生代三者的GC

  为什么需要了解GC和内存分配?

  当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,就需要对这些“自动化”的技术实施必要的监控和调节。

  在java内存运行时区域的各个部分中,程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几部分区域的内存分配和回收都具有确定性,不需要考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟着回收了。而java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样。只有在程序处于运行期时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的就是这部分内存。

2.判断对象是否已死

  (1) 引用计数法

    给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。主流的java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因就是它很难解决对象之间相互循环引用的问题。

  (2) 可达性分析算法

    算法的基本思想就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

  在java语言中,可作为GC Roots的对象包括下面几种:

    a.虚拟机栈(栈帧中的本地变量表)中的引用的对象

    b.方法区中类静态属性引用的对象

    c.方法区中常量引用的对象

    d.本地方法栈中JNI(Native方法)引用的对象

  判断一个类是否是“无用的类”的条件为:

    a. 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例

    b. 加载该类的ClassLoader已经被回收

    c. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

3. 垃圾收集算法

  (1) 标记--清除

    标记清除算法是最基础的算法,算法分为“标记”和“清除”两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

    不足:一个是效率问题,标记和清除两个过程两个过程效率都不高;另一个是空间问题,标记清除之后会产生大量的不连续的内存碎片,空间碎片太多可能导致之后需要分配大量内存对象时,无法找到足够的连续的内存而不得不提前触发另一次垃圾收集动作。

    

                                

  (2) 复制算法

    将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂的情况了,实现简单,运行高效,代价为将内存缩小为原来的一半。这种方法适用于回收新生代。

               

  (3) 标记--整理算法

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

    

  (4) 分代收集算法

    在新生代中,每次垃圾收集时都发现大批对象死去,只有少量存活,选择复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就需要使用标记清理或者标记整理的算法来回收。

4.垃圾收集器

  如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

  (1) Serial收集器

    它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。适用于新生代。

  (2) ParNew收集器

    ParNew收集器就是Serial收集器的多线程版本。

  (3) Parallel Scavenger收集器

    Parallel Scavenger收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。

  (4) Serial Old收集器

    Serial Old收集器是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记清理”算法。

  (5) Parallel Old 收集器

    Parallel Old 是 Parallel Scavenger收集器的老年代版本,使用多线程和“标记整理”算法。

  (6) CMS 收集器

    CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记清除”算法实现的。整个步骤分为:

    a. 初始标记

    b. 并发标记

    c. 重新标记

    d. 并发清除

  (7) G1收集器

    优点:并行和并发,分代收集,空间整合,可预测停顿。

5. 内存分配

  (1) 对象优先在Eden分配

    大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。

  (2) 大对象直接进入老年代

    大对象是指需要连续内存空间的java对象,最典型的大对象就是很长的字符串以及数组。经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获取足够的连续空间来“安置”它们。

  (3) 长期存活的对象将进入老年代

    虚拟机为每一个对象定义一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,将被移动到Survivor空间中,并设置对象年龄为1.当年龄增加到一定程度(默认为15岁),就会被晋升到老年代。

  (4) 动态对象年龄判定

    如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄的对象就可以直接进入老年代,无须等到阈值年龄。

  (5) 空间分配担保

6. 内存分析工具

  (1) Jmc

    java 7u40发布中加入的性能监控工具。功能全面,包括CPU占用率、内存使用情况、I/O耗时等。常用于性能分析。

  (2) Jconsole

    jdk自带的可视化监视和管理控制台。监控某个进程的内存、线程、类等信息。可观察堆内存新生代、老年代的使用情况。

  (3) Jvisualvm

    jdk自带的可远程或本地监控内存泄漏,跟踪垃圾回收的工具。可以dump堆内存数据

  (4) Eclipse Memory Analyzer

    是分析堆数据的专业工具,可以定位内存泄漏的原因。

    

    

    

    

  

GC垃圾回收器的更多相关文章

  1. [Java基础]-- Java GC 垃圾回收器的分类和优缺点

    https://blog.csdn.net/high2011/article/details/80177473?utm_source=blogxgwz2 参考:elasticsearch实战-使用G1 ...

  2. 一篇文章让你了解GC垃圾回收器

    简单了解GC垃圾回收器 了解GC之前我们首先要了解GC是要做什么的?顾名思义回收垃圾,什么是垃圾呢? GC回收的垃圾主要指的是回收堆内存中的垃圾对象. 从根对象出发,所有被引用的对象,都是存活对象 其 ...

  3. .NET GC垃圾回收器

    GC垃圾回收器简介 全名: Garbage Collector 原理: 以应用程序的根(root)为基础,遍历应用程序堆(heap)上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是已经死亡 ...

  4. 如何获取GC(垃圾回收器)的STW(暂停)时间?

    前言 在现代的容器化和微服务应用中,因为分布式的环境和错综复杂的调用关系,APM(Application Performance Monitoring 应用性能监控)显得尤为重要,它通过采集应用程序各 ...

  5. GC(垃圾回收器)中的算法

    GC的两种判定方法 (1) 引用计数法 给对象添加一个引用计数器,每当引用一次+1,每次失效时-1,当计数器为0时,表示对象就是不可能再被使用的. (2) 可达性分析算法 将“GC Roots”对象作 ...

  6. Java虚拟机笔记(二):GC垃圾回收和对象的引用

    为什么要了解GC 我们都知道Java开发者在开发过程中是不需要关心对象的回收的,因为Java虚拟机的原因,它会自动回收那些失效的垃圾对象.那我们为什么还要去了解GC和内存分配呢? 答案很简单:当我们需 ...

  7. Android内存优化5 了解java GC 垃圾回收机制3

    引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...

  8. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  9. C#.Net GC(garbage Collector) 垃圾回收器

    以前一直以为gc的原理很简单,也就是分代处理堆数据,直到我的膝盖中了一箭(好吧 直到有天汪涛和我说他面试携程的面试题 关于服务器和 工作站gc 的区别)其实我当时尚不知道 工作站和服务器有什么区别更不 ...

随机推荐

  1. kuda 了解片

    本来上个月想去了解一下kuda的,结果一直没有抽出时间去搞,现在大致先开个头,方便后面深入! Apache Kudu是开源Apache Hadoop生态系统的新成员,它完善了Hadoop的存储层,可以 ...

  2. js 动态生成html 触发事件传参字符转义

    通常,在使用 JS 动态生成 html 的过程中,会嵌入相应的样式.事件等属性元素,而这时经常会出现所谓的 “单.双引号不够用” 的情况,别急,这时可以利用 html 语言中的转义字符来解决.下面就来 ...

  3. 画图必备numpy函数

    给定一堆数字,需要统计这些数字中每个数字的个数. 如果这些数字是整数,那自然可以精确统计出来. 如果这些数字是浮点数,如果精确统计会发现几乎每个数字都只出现了一次.所以浮点数就要通过区间的方式进行统计 ...

  4. asp.net中 使用参数化mysqlparameter 保存数据时,总保存成一个汉字的解决方案。

    var param = new MySqlParameter("@" + columName, property.Value); param.DbType = DbType.Str ...

  5. 设置 WPF 的内容支持触摸直接滚动

    在滚动内容上设置属性 ScrollViewer.PanningMode 的值即可. 另外可重写 OnManipulationBoundaryFeedback 方法来替换系统默认的滚动到最上最下时触发的 ...

  6. TensorFlow官网无法访问

    相信很多搞深度学习的小伙伴最近都为访问不了 TensorFlow官网 而苦恼吧!虽然网上也给出了一些方法,但是却缺少一个很重要的步骤.接下来,我就给大家讲解一个完整的过程,大牛绕过. 1.更改Host ...

  7. 【原创 Hadoop&Spark 动手实践 9】Spark SQL 程序设计基础与动手实践(上)

    [原创 Hadoop&Spark 动手实践 9]SparkSQL程序设计基础与动手实践(上) 目标: 1. 理解Spark SQL最基础的原理 2. 可以使用Spark SQL完成一些简单的数 ...

  8. nlp资料网站

    原文地址 http://blog.sina.com.cn/s/blog_574a437f01019poo.html 昨天实验室一位刚进组的同学发邮件来问我如何查找学术论文,这让我想起自己刚读研究生时茫 ...

  9. Spark 广播变量BroadCast

    一. 广播变量 广播变量允许程序员将一个只读的变量缓存在每台机器上,而不用在任务之间传递变量.广播变量可被用于有效地给每个节点一个大输入数据集的副本.Spark还尝试使用高效地广播算法来分发变量,进而 ...

  10. [转]Eureka自我保护机制、健康检查的作用、actuator模块监控

    Eureka自我保护机制 接着以上篇文章建立的三个工程为基础(eureka-server,uerreg,myweb),默认Eureka是开启自我保护的.我们来做个测试,我们先启动三个工程,我们访问注册 ...