垃圾收集器与内存分配策略

垃圾收集,三个步骤

什么时候收集,收集那些,怎么收集

1、收集那些

我们会将一些不使用的对象进行收集,进行回收内存空间,我们怎么知道呢

1、引用计数法

如果这个实例被其他地方引用,那么计数器加一,如果解除引用那么就减一,当计数器为0说明没有地方使用,即可回收,但是缺点就是如果两个对象互相引用,但是后续又用不到,那么就不会被回收,内存浪费

2、可达性分析

通过GC Root向下寻找,形成一条引用链,如果对象不再这条链上,那么说明该对象不可达,可回收,

什么是GC Root虚拟机栈中引用的对象

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

方法区常亮引用的对象

本地方法栈中引用的对象

3、引用

我们不论是使用引用计数法,还是使用可达性分析,都有引用这个词,什么意思呢

jdk1.2之前的引用,是reference类型的数据存储的是另一块内存的起始地址,那么就称这块内存代表着一个引用,这种情况下,一个对象只有被引用和没有被引用两种状态,

我们希望有一些对象,在内存空间足够的时候,能够保留在内存中,如果内存空间在进行垃圾收集之后还是很紧张,那么就抛弃这些对象,所以出现 强引用(Strong Reference),软引用(Soft Reference),弱引用(Weak Reference),虚引用(Phantom Reference),这4中引用强度依次减弱强引用

强引用就是指程序代码中普遍存在的 Object obj = new Object()这类引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象,使用StrongReference实现

软引用

jdk1.2之后出现软引用用来描述一些有用,但不是必须的对象,软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列入可回收范围中进行第二次回收,如果这次回收还不能解决内存问题,那么抛出内存溢出错误,,使用SoftReference实现

弱引用

弱引用也是用来描述非必需的对象,被弱引用关联的对象,只能生存到下一次垃圾收集发生之前,当垃圾收集器工作时候,无论当前内存是否足够,都会回收掉,使用WeakReference类实现虚引用

虚引用

最弱的引用,一个对象是否有徐勇勇的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例,为一个对象设置虚引用关联的唯一目的,就是能在这个对象被收集器回收时收到一个系统通知,jdk1.2之后通过PhantomReference类来实现虚引用,

4.对象死了吗

当对象没有存在GC Root引用链上,也不是马上死,会被进行一次标记并进行一次筛选,查看对象的finalliaze方法是否被覆盖,或者是否被虚拟机调用过了,

如果被覆盖或者没有被调用,那么这个对象会被放置到F-Queue中,等待执行finaliaze方法,虚拟机会开启一条低优先级的线程去触发这些方法,如果对象在finalize方法中重新加入了引用链(把自己赋值给某个类变量,或者对象的成员变量),那么就不会被回收了,

5.回收方法区

回收方法区内废弃常量和无用的类

废弃常量:如果常量池中有各“abc”的字面量,但是却没有一个string 对象叫做abc,那么这个就是废弃常量,当垃圾回收的时候就会回收

无用的类:在堆中已经没有这个类的实例,加载该类的类加载器已经被回收,这个Class对象没有在任何地方被引用,无法通过反射获取这个类的方法

2、怎么收集

垃圾收集在方法区和堆区

1.标记-清除算法

标记清除:当堆内存耗尽的时候,触发GC线程,使用户线程停止,遍历所有的GC root,将还存活的随想标记一下,之后清除所有未标记的对象,继续用户线程,缺点:产生内存碎片,使得内存不连续,当有对象申请大内存的时候,出现问题

复制算法: 将原内存一分为二,只用一半的内存,当需要垃圾回收的时候, 标记存活对象,然后将存活对象拷贝到另一半空间中去,前一半直接全部回收,缺点:无论什么时候,只有一半的内存可用,浪费,拷贝对象需要时间

标记整理算法:标记存活对象,将存活对象按照某种规则排列,清除别的对象,缺点:需要遍历标记,需要移动对象,浪费时间

分代回收:

堆分为新生代和老年代,新生代分三个模块,Enden surviver0 surviver1  8:1:1  new出来的对象放在enden区域,当发生gc,将存活的放在surviver0,第二次将存活的,surviver0中的放在surviver1中,反复如此,使用标记复制算法,当新生代的对象活过一定次数gc,就会去到老年代

新生代使用复制算法,老年代使用标记清除,标记整理算法

3、常见的垃圾收集器

1.Serial垃圾收集器(客户端模式下的虚拟机,新生代默认收集器)

单线程垃圾收集器,在进行垃圾收集的时候,会停止用户线程,当垃圾收集完毕,开始用户线程,这个是对用户不可见的,完全由虚拟机执行,单CPU效率最高的收集器,没有线程交替的开销

2.ParNew垃圾收集器(服务端模式下的虚拟机,新生代默认收集器)

Serial收集器的多线程版本,在进行垃圾收集,也会先停止用户线程,除了Serial只有这个收集器可以和CMS收集器使用,

3. Parallel Scavenge收集器

多线程并行的垃圾收集器,与ParNew类似,但是这个收集器注点在于达到一个可控制的吞吐量,吞吐量就是CPU用于运行用户代码的时间与cpu总消耗时间的比值,

4. Serial Old收集器

是serial收集器的老年版本,同样是一个单线程收集器,使用标记整理算法,是给客户端模式下的虚拟机使用,在server模式下的客户端有两大用途:一是在jdk1.5之前,与Parallel Scavenge收集器搭配使用,二就是作为CMS收集器的后备预案,在并发收集器发生Concurrent Mode Failure时使用,

也会暂停用户线程

5. CMS收集器

是一种以获取短回收停顿时间为目标的收集器,采用标记清除方式,运作过程有初始标记

并发标记

重新标记

并发清除

其中初始标记与重新标记需要停止用户线程,初始标记只是标记一下GC Root能直接关联到的对象,速度很快,并发标记阶段就是进行GC Root Tracing的过程,而重新标记阶段则是为了修正并发标记期间因为用户程序继续运作而导致的标记产生变动的那一部分对象的记录,这个阶段停顿的时间一般会比初始标记阶段稍长一点,但远比并发标记的时间短,,由于整个过程中耗时最长的并发标记和并发清除过程,收集器线程可以和用户线程一起工作,所以,总体来看,CMS收集器的内存回收过程食欲用户线程一起并发执行的,

缺点:CMS无法处理浮动垃圾,可能出现Concurrent Mode Failure失败而导致另一次Full GC的产生,由于CMS的并发清理阶段适合用户线程一起的,那么程序运行就会有新的垃圾产生,这一部分垃圾在标记之后,所以CMS不会处理,下一次处理, 也是由于在垃圾收集阶段用户线程还需要运行,那也就是需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全填满在进行收集,需要留一部分空间提供并发收集时的程序运作使用,当在CMS运行期间预留的内存无法满足程序需要就会出现一次Concurrent Mode Failure失败,这个时候就会启动Serial Old收集器进行老年代的垃圾收集,

6. G1收集器

具有以下特点,并行与并发

充分利用多核多CPU,缩短Stop The World的时间,G1收集器通过并发的方式让java程序继续执行

分代收集

与其他收集器一样,分代概念也在G1中保存,G1不需要通过其他收集器配合就可以管理真个堆,但是它可以通过不同的方式处理,

空间整合

G1从整体来看是基于标记整理算法实现的,从局部来看是基于复制算法实现的,不会产生内存碎片,收集后能提供规整的可用内存,不会因为分配大对象找不到连续内存空间触发GC

可预测的停顿

G1可以让使用者明确指定在一个长度为n毫秒的时间片段内,消耗在垃圾收集上的时间不能超过n毫秒,

作者:z七夜

链接:https://www.jianshu.com/p/e4dd7f5329a1

java内存分配和垃圾回收_深入理解java虚拟机(二)垃圾收集器与内存分配策略...相关推荐

  1. 【Android 内存优化】垃圾回收算法 ( 分代收集算法 | Serial 收集器 | ParNew 收集器 | Parallel Scavenge 收集器 | CMS 并发标记清除收集器 )

    文章目录 一. 分代收集算法 二. 垃圾回收器 / 收集器 ( GC ) 三. 串行收集器 ( Serial ) 四. ParNew 收集器 五. Parallel Scavenge 收集器 六. C ...

  2. java虚拟机手动内存分配_《深入理解java虚拟机》-垃圾收集器与内存分配策略

    如何判断对象已死? 引用计数算法 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1:当引用失效时,计数器减1:其中计数器为0的对象是不可能再被使用的已死对象. 引用计数算法的实现很简单 ...

  3. java final 垃圾回收_新的Java垃圾回收机制ZGC 简介

    垃圾回收是Java的一项重要机制,是二月份的一项学习计划之一. ZGC是一种较新的垃圾回收机制,在JDK11中实验性引入,看了R大的几篇文章,依然不懂,之后发现了一篇介绍地比较易懂的文章: 希望对你有 ...

  4. java为什么要分代回收_浅谈Java堆内存分代回收

    1.概述 与C++不同的是, 在Java中我们无需关心对象占用空间的释放, 这主要得益于Java中的垃圾处理器(简称GC)帮助我们自动的进行对象占用空间的释放. 下面我们带着几个问题来学习: 堆内存是 ...

  5. JVM垃圾回收机制总结(3) :按代垃圾收集器

    全文转载:http://pengjiaheng.iteye.com/blog/524024 作者:和你在一起 [from JavaEye] 为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的 ...

  6. java的跨平台特性是指_如何理解JAVA的跨平台特性

    1.java的跨平台,是指java在运行时是凌驾于os之上,是在jvm中运行的,跟os没有直接联系. 2.java跨平台主要是由java的编译方式决定的,因为java是通过jvm先编译再执行,它编译的 ...

  7. java实例化类之后如何赋值_深入理解Java对象的创建过程:类的初始化与实例化...

    摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...

  8. java中线程调度遵循的原则_深入理解Java多线程核心知识:跳槽面试必备

    多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲.在平时工作中如若使用不当会出现数据错乱.执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关 ...

  9. Java基本数据类型的自动转换_彻底理解Java中的基本数据类型转换(自动、强制、提升)...

    说基本数据类型转换之前,先了解下 Java 中的 8 种基本数据类型,以及它们的占内存的容量大小和表示的范围,如下图所示. 重新温故了下原始数据类型,现在来解释下它们之间的转换关系. 自动类型转换 自 ...

最新文章

  1. centos安装软件_CentOS 8 和 Ubuntu 18.04 部分软件版本比较
  2. python把坐标写入文本_Python实现将数据写入netCDF4中的方法示例
  3. NYOJ541 最强DE 战斗力(第五届省赛试题)
  4. SAP Spartacus 服务器端 nodejs 应用里渲染 Angular Component 的一个例子
  5. 幼儿园调查过程怎么写_深圳全托幼儿园哪个好 幼儿园寄宿怎么报名
  6. Django(四)数据库
  7. 机器学习之开源库大总结
  8. Linux中使用sftp的常用命令
  9. 智能网联汽车云控系统第2部分:车云数据交互规范
  10. java计算机毕业设计劳务外包管理系统源码+系统+mysql数据库+lw文档
  11. 如何将pdf文件转换成图片?
  12. 计算机中的right函数,excel的right函数的使用教程
  13. 【博客559】更出色的网络监控采集方案---Telemetry(遥测技术)
  14. 偷偷告诉你中国小姐姐的真实Size!!
  15. 墨尘 - UE4 入门教程笔记 —— 二
  16. python 背景音乐程序代码_python 喜马拉雅 音乐下载 演示代码
  17. 修改HTK代码,让其支持中文
  18. 限制Teams会议中的聊天
  19. mysql常用操作(二)
  20. Linux中动态探针kprobes

热门文章

  1. 计算机视觉自学进阶路上不可忽略的几个原创公众号
  2. IDA Linux远程调试
  3. Vue的全局事件总线实现任意组件间通信
  4. 要怎么在计算机里清除桌面内存,电脑内存不足怎么办?怎么清理电脑内存?
  5. RANSAC点云多平面拟合分割
  6. vue支付宝html,Vue的H5页面唤起支付宝支付功能
  7. 1篇文章带你了解poco的所有基本功能(含演示demo)
  8. 2016年蓝桥杯预赛第十题最大比例
  9. 既然硕士毕业也去搞开发,那还去读研值吗?
  10. 去中心化区块链预言机