前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java的GC和内存分配策略

Java的GC和内存分配策略

作者头像
cwl_java
发布2019-10-26 20:40:27
7400
发布2019-10-26 20:40:27
举报
文章被收录于专栏:cwl_Javacwl_Java

1.概述

代码语言:javascript
复制
学习GC需要搞懂以下三个问题:
  • 1.1 哪些内存需要回收
  • 1.2 什么时候回收
  • 1.3 如何回收
问题1

哪些内存需要回收,这个问题指向的就是堆空间当中存放着的对象实例,这一部分是可以动态变化的,所以GC的第一步就是需要判断在这个堆空间当中哪些对象还存活着

  • 解决方法

1.引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用,则计数器+1,当引用失效则计数器-1,当计数器为0,则GC可以进行回收

2.可达性分析算法:通过GC root作为起点,寻找一个对象被引用过程的引用链,当引用链的结果不可达的时候,说明该对象是可以被回收的

Java中的引用

在JDK1.2之前,Java中的引用只有引用和没有引用两种情况,但是在开发过程中,我们往往需要更加复杂的场景,例如当我们内存空间足够的时候,我们就讲对应的对象存储在内存中,当我们内存不足的时候我们就把它进行回收,所以JDK1.2之后,开始对引用进行了区分,分成了以下四种形式

  • 强引用 : 使用new Object()创建出来的对象,只要在代码中还在运行,那么它就不会被GC所回收
  • 软引用 : 类似于对象当中的关联对象,当内存即将溢出之前,软引用会被GC回收
  • 弱引用 : 用来描述非必须的对象,不管当前内存是否不足,都会被GC列为需要回收的对象
  • 虚引用 : 唯一目的就是能在这个对象被收集器回收时收到一个系统通知
回收方法区

对于回收方法区它的性能肯定是不如回收堆空间来的简单,因为堆空间比方法区会更加消耗内存.但是对于方法区而言也是有两种东西需要回收的,一种是废弃常量,另一种是无用的类.相对的废弃常量判定方法比较简单,没有对它的引用,就说明该常量已经废弃,但是对于无用的类判定的方法就比较复杂,需要满足以下几个条件

  • 1.该类的所有实例都已经被回收,也就是在堆空间当中已经不存在该类的实例对象了
  • 2.该类的ClassLoader已经被回收了
  • 3.该类的反射对象也在任何地方都没有被引用

综上所述:GC在方法区当中的回收对废弃常量来说还算比较划算,但是对于无用的类则是性价比比较低的,因为本来类加载器就是根据该类是否被用到,从而来将该类加载到内存当中的,然而如果该类已经不存在任何引用了,那么说明这部分的程序也已经基本跑到头了

GC算法

1.标记-清除算法:正如算法名字,该算法分成了标记和清除两个部分,标记部分如上所述的引用计数算法,标记完成之后进行清除部分

2.复制算法:复制算法的做法就是将所有堆空间当中的内存都复制一遍,然后当这些对象被使用过后,就会把这些复制出来的全部都清除,优点就是运行高效,不必考虑内存碎片问题,(内存碎片在多个对象相互引用的过程中没有全部清除,最终产生内存碎片)缺点是会将整个堆内存空间缩小到原来的一半,从而付出了很大的内存消耗

3.标记-整理算法:标记整理算法跟标记清除算法类似,标记过程相同,不同的是标记的结果不是为了清除,而是为了让所有对象在内存空间当中有序的往一个方向移动,并且设定一个内存边界,只是对内存边界以外的进行清理

4.分代收集算法:分代收集算法并不是一种新的算法,而是根据不同的堆空间(新生代,年老代,永久代[方法区]),采用不同的算法.例如对于新生代而言采用复制算法比较合适,因为在这个空间意味着有较多的短时间引用的对象被不断的创建和销毁,相比之下年老代就更加适合使用标记-清除算法或者是标记-整理算法,对于那些已经有不断被引用,然而即将不再被引用的对象进行清理操作

GC(垃圾收集器)
代码语言:javascript
复制
对于我们最常用的JVM HotSpot,它本身也有自带了很多个GC,不同的GC会有不同的一些效用,可以进行搭配使用
  • 1.Serial收集器

Serial收集器是一个比较霸道的收集器,本身它在进行垃圾回收的时候是单线程操作的,它的单线程不仅仅是自己的单线程,它还会在运行前发起指令终止其他的线程,以达到它单线程的目的.所以它也有一个绰号叫做"stop the world"

  • 2.ParNew收集器

ParNew收集器简单来说就是楼上的Serial收集器的升级版,相当于同时开启了多个Serial收集器去工作,其它方面并没有什么创新之处

  • 3.Parallel Scavenge收集器

Parallel Scavenge收集器是一个新生代的收集器,跟ParNew一样是一个多线程的收集器,但是它更强调的是可控的吞吐量,提供了可以用于控制平衡的吞吐量 吞吐量=CPU运行用户代码时间/CPU总耗时

  • 4.Serial Old收集器

Serial Old是Serial收集器的老年代版本,同样是单线程收集器,算法使用的是标记-整理算法,其余跟Serial收集器没有什么太大区别 本质上说垃圾收集器就是类似于妈妈在打扫房间,虽然你会觉得Serial收集的做法很霸道,当它在运行的时候就不允许其他线程运行,但是你想想,如果你妈妈在打扫房间的时候,你还在一边扔纸屑打扰她,试想一下是不是也很不合理

  • 5.Parallel Old收集器

其实本质上就是Parallel Scavenge的收集器的老年代版本,采用的是标记-整理的算法

CMS收集器

需要重点介绍的一款GC,在JDK1.5~JDK1.7之间基本采用的都是CMS作为GC来管理内存.全称是Concurrent Mark Sweep,顾名思义采用的是标记-清除的算法,目标是达到最短回收停顿时间.过程分成了4个步骤

  • 1.初始标记
  • 2.并发标记
  • 3.重新标记
  • 4.并发清除

初始标记和重新步骤仍旧需要"Stop the world",但是由于初始标记只是标记GC Roots的初始节点,所以速度会很快 CMS是一款十分优秀的收集器,也是目前B/S开发模式比较常用的GC收集器.它的特点是并发收集,低停顿.主要来源于它对CPU的敏感度给常高,它虽然不会导致用户的其它线程停顿,但是会导致其它应用程序变慢,吞吐量会变慢,CMS默认启动的回收线程数=(CPU数量+3)/4,当CPU数量为4的时候,那么资源占用为25%,但是当CPU数量小于等于2的时候,那么资源占用率就至少达到了72.5% 综上所述:对于高性能的服务器,具备4个以上的CPU来说,采用CMS垃圾收集器是非常可观的

G1收集器

从JDK1.7开始逐渐开始替代了CMS收集器在JavaGC中的地位.它具备了以下几个以前的那些GC没有的特点

  • 1.并行与并发:G1收集器相比于CMS按照CPU占比来减少Stop-the-world的时间,G1对此是使用并发的方式来保证GC运行和用户线程的同时使用,这就是把对CPU资源的调用权还给了CPU自身
  • 2.分代收集:G1可以选择自己独立管理堆内存,也可以选择跟其他的GC回收器一起进行管理
  • 3.空间整合:更有利于程序的长时间运行,分配大对象时不会因为无法找到连续的内存空间而提前触发了GC
  • 4.可预测的停顿:可以设置垃圾收集的时间最大值不超过N毫秒
  • 5.GI的执行过程
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选标记
对象分配原则
  • 1.优先分配在新生代Eden区中,当Eden区当中空间不足时,触发Minor GC
  • 2.大对象或者是长期存活调用频繁的对象会进入到年老代,当年老代空间不足时会触发Major GC,Major GC的触发往往会伴随着一次Minor GC的发生,当Major GC触发之后就距离Full GC不远了,如果Full GC依旧不能解决问题,那么就会导致内存的溢出
  • 3.从JDK1.8的版本开始,已经取消了永久代,取而代之的是Meta Space,这个空间是可以自动拓展的,好处是提高了该部分存储空间的灵活性,但是坏处就是降低了堆内存空间的性价比
  • 4.能够进入年老代的还有对象年龄达到了MaxenuringThreshold的对象,Survivor空间中相同年龄所有对象大小综合大于Survivor空间的一半的也会直接进入年老代,这是对此类动态对象的判定规则
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.概述
    • 问题1
      • 回收方法区
        • GC算法
          • GC(垃圾收集器)
          • CMS收集器
          • G1收集器
            • 对象分配原则
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档