前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java垃圾回收机制(Garbage Collection)--笔记

Java垃圾回收机制(Garbage Collection)--笔记

作者头像
逆回十六夜
修改2019-08-08 10:20:04
1.1K0
修改2019-08-08 10:20:04
举报
文章被收录于专栏:逆回十六夜逆回十六夜

学习笔记摘自https://www.bilibili.com/video/av30023103/?p=67

内存管理

java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。

对象空间的分配:使用new关键字创建对象即可

对象空间的释放:将对象赋值null。垃圾回收期负责回收所有“不可达”对象的内存空间。

垃圾回收的过程

任何一种垃圾回收算法一般要做两件基本事情

1.发现无用的对象

2.回收无用对象占用的内存空间

垃圾回收机制保证可以将“无用的对象”进行回收。无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关的算法发现无用的对象,并且进行清除和管理。

垃圾回收的相关的算法

1.引用计数法

堆中的每个对象都有一个引用计数,被引用一次,计数加1,被引用变量值变为null,则计数减1,计数为0,则表示变为无用对象,算法简单,但是无法识别循环引用

循环引用示例:

2.引用可达法

程序把所有的引用关系看做一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。emmm,这里的引用应该是全局的寻找的,绝不仅仅是堆或者栈。

通用的分代垃圾回收机制

----------------------------------------------------------------------------------------------------------------------------------------------------------

如何解决同时存在的对象创建和对象回收问题

    垃圾回收线程是回收内存的,而程序运行线程则是消耗(或分配)内存的,一个回收内存,一个分配内存,从这点看,两者是矛盾的。因此,在现有的垃圾回收方式中,要进行垃圾回收前,一般都需要暂停整个应用(即:暂停内存的分配),然后进行垃圾回收,回收完成后再继续应用。这种实现方式是最直接,而且最有效的解决二者矛盾的方式。

但是这种方式有一个很明显的弊端,就是当堆空间持续增大时,垃圾回收的时间也将会相应的持续增大,对应应用暂停的时间也会相应的增大。一些对相应时间要求很高的应用,比如最大暂停时间要求是几百毫秒,那么当堆空间大于几个G时,就很有可能超过这个限制,在这种情况下,垃圾回收将会成为系统运行的一个瓶颈。为解决这种矛盾,有了并发垃圾回收算法,使用这种算法,垃圾回收线程与程序运行线程同时运行。在这种方式下,解决了暂停的问题,但是因为需要在新生成对象的同时又要回收对象,算法复杂性会大大增加,系统的处理能力也会相应降低,同时,“碎片”问题将会比较难解决。

由于不同对象的生命周期不一样,因此在JVM的垃圾回收策略中有分代这一策略。本文介绍了分代策略的目标,如何分代,以及垃圾回收的触发因素。

文章总结了JVM垃圾回收策略为什么要分代,如何分代,以及垃圾回收的触发因素。

为什么要分代

        分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

        在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。

        试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

原文链接:https://blog.csdn.net/lufeng20/article/details/7402386

-----------------------------------------------------------------------------------------------------------------------------------------------------------

分代垃圾回收机制,是基于这样一个事实:不同的对象的生命周期是不一样的,因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率,我们讲对象分为三种状态:年轻代,年老代,持久代。JVM将堆内存划分为Eden(伊甸园),Survivor和Tenured(终身的,长期的)/Old空间

1.年轻代

所有新生成的对象首先都是放到Eden去。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC(Minor未成年),每次Minor GC会清理年轻代的内存,算法采取效率较高的复制算法,频繁的操作,但是会浪费内存空间。当年轻代的区域放满对象后,就将对象存放到年老代的区域。

2.年老代

在年轻代中经历了N(默认15)次垃圾回收之后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代的对象越来越多,我们就需要启动Major GC和Full GC(全量回收)来一次大扫除,全面的清理年轻代区域和年老代区域。

3.持久代

用于存放静态文件,如Java类,方法等。持久代对垃圾回收没有显著影响。

垃圾回收的过程:

1.新创建的对象,绝大多数都会存储在Eden中

2.当Eden满了(达到了一定的比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区

3.当Eden再次满了,会将S1中不能清空的对象存储到另一个Survivor中,如S2,同时将Eden区中不能清空的对象也复制到S1,保证Eden和S1均被清空。

4.重复多次(默认15次)Survivor中没有被清理的对象,则被复制到老年代Old(Tenured)中.

5.当Old去也满了,则会触发完整的垃圾回收机制(FullGC),之前新生代的垃圾回收成为minorGC

JVM调优和Full GC

在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节,有如下的原理可能导致Full GC:

  • 年老代(Tenured/Old)被写满
  • 持久代 (Perm)被写满
  • System.gc()被显示调用(这句话只是向程序建议GC,而不是一定会调用GC)
  • 上一次GC之后heap的各域分配策略动态变化。

本文系转载,前往查看

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

本文系转载前往查看

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内存管理
    • 垃圾回收的过程
    • 垃圾回收的相关的算法
      • 1.引用计数法
        • 2.引用可达法
          • 如何解决同时存在的对象创建和对象回收问题
          • 为什么要分代
      • 通用的分代垃圾回收机制
        • 1.年轻代
          • 2.年老代
            • 3.持久代
              • 垃圾回收的过程:
                • JVM调优和Full GC
                相关产品与服务
                对象存储
                对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档