阅读更多

0顶
0踩

编程语言

转载新闻 什么是垃圾回收

2015-06-11 10:25 by 正式记者 黑客不黑 评论(0) 有6797人浏览
本文摘自我们几周后即将出版的Garbage Collection Handbook一书的样章。同时也让你能熟悉下垃圾回收的基础知识——这选自该书的第一章。

乍一看,垃圾回收所做的事情应当恰如其名——查找并清除垃圾。事实上却恰恰相反。垃圾回收会跟踪所有仍在使用的对象,然后将剩余的对象标记为垃圾。牢记了这点之后,我们再来深入地了解下这个被称为“垃圾回收”的自动化内存回收在JVM中到底是如何实现的。

手动管理内存

在介绍现代版的垃圾回收之前,我们先来简单地回顾下需要手动地显式分配及释放内存的那些日子。如果你忘了去释放内存,那么这块内存就无法重用了。这块内存被占有了却没被使用。这种场景被称之为内存泄露。

下面是用C写的一个手动管理内存的简单例子:
int send_request() {
    size_t n = read_size();
    int *elements = malloc(n * sizeof(int));
 
    if(read_elements(n, elements) < n) {
        // elements not freed!
        return -1;
    }
 
    // …
 
    free(elements)
    return 0;
}

可以看到,你很容易就会忘了释放内存。内存泄露曾经是个非常普遍的问题。你只能通过不断地修复自己的代码来与它们进行抗争。因此,需要有一种更优雅的方式来自动释放无用内存,以便减少人为错误的可能性。这种自动化过程又被称为垃圾回收(简称GC)。

智能指针
自动垃圾回收早期的一种实现便是引用计数。你知晓每一个对象被引用了几次,当计数器归0的时候,这个对象就可以被安全地回收掉了。C++的共享指针就是一个非常著名的例子:
int send_request() {
    size_t n = read_size();
    stared_ptr<vector<int>> elements 
              = make_shared<vector<int>&gt();
 
    if(read_elements(n, elements) < n) {
        return -1;
    }
 
    return 0;
}

我们使用的sharedptr会记录这个对象被引用的次数。如果你将它传递给别人则计数加一,当它离开了作用域后便会减一。一旦这个计数为0,sharedptr会自动地删除底层对应的vector。当然这只是个示例,因为也有读者指出来了,这个在现实中是不太可能出现的,但作为演示是足够了。

自动内存管理

在上面的C++代码中,我们还得显式地声明我们需要使用内存管理。那如果所有的对象都采用这个机制会怎样呢?那简直就太方便了,这样开发人员便无需考虑清理内存的事情了。运行时会自动知晓哪些内存不再使用了,然后释放掉它。也就是说,它自动地回收了这些垃圾。第一代的垃圾回收器是1959年Lisp引入的,这项技术迄今为止一直在不断演进。

引用计数
刚才我们用C++的共享指针所演示的想法可以应用到所有的对象上来。许多语言比如说Perl, Python以及PHP,采用的都是这种方式。这个通过一张图可以很容易说明:



绿色的云代表的是程序中仍在使用的对象。从技术层面上来说,这有点像是正在执行的某个方法里面的局部变量,亦或是静态变量之类的。不同编程语言的情况可能会不一样,因此这并不是我们关注的重点。

蓝色的圆圈代表的是内存中的对象,可以看到有多少对象引用了它们。灰色圆圈的对象是已经没有任何人引用的了。因此,它们属于垃圾对象,可以被垃圾回收器清理掉。

看起来还不错对吧?没错,不过这里存在着一个重大的缺陷。很容易会出现一些孤立的环,它们中的对象都不在任何域内,但彼此却互相引用导致引用数不为0。下面便是一个例子:



看到了吧,红色部分其实就是应用程序不再使用的垃圾对象。由于引用计数的缺陷,因此会存在内存泄露。

有几种方法可以解决这一问题,比如说使用特殊的“弱”引用,或者使用一个特殊的算法回收循环引用。之前提到的Perl,Python以及PHP等语言,都是使用类似的方法来回收循环引用的,不过这已经超出本文讲述的范围了。我们准备详细介绍下JVM所采用的方法。

标记删除

首先,JVM对于对象可达性的定义要明确一些。它可不像前面那样用绿色的云便含糊了事的,而是有着非常明确及具体的垃圾回收根对象(Garbage Collection Roots)的定义:
  • 局部变量
  • 活动线程
  • 静态字段
  • JNI引用
  • 其它(后面将会讨论到)

JVM通过标记删除的算法来记录所有可达(存活)对象,同时确保不可达对象的那些内存能够被重用。这包含两个步骤:
  • 标记是指遍历所有可达对象,然后在本地内存中记录这些对象的信息
  • 删除会确保不可达对象的内存地址可以在下一次内存分配中使用。

JVM中的不同GC算法,比如说Parallel Scavenge,Parallel Mark+Copy, CMS都是这一算法的不同实现,只是各阶段略有不同而已,从概念上来讲仍然是对应着上面所说的那两个步骤。

这种实现最重要的就是不会再出现泄露的对象环了:



缺点就是应用程序的线程需要被暂停才能完成回收,如果引用一直在变的话你是无法进行计数的。这个应用程序被暂停以便JVM可以收拾家务的情况又被称为Stop The World pause(STW)。这种暂停被触发的可能性有很多,不过垃圾回收应该是最常见的一种。

转自:花名有孚
  • 大小: 39.2 KB
  • 大小: 46.2 KB
  • 大小: 45.5 KB
来自: 花名有孚
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 什么是垃圾回收机制(超详细)

    1.垃圾回收机制(Garbage Collction)简称GC,是JavaScript中使用的内存管理系统的基本组部分,是为了防止内存泄漏2.JavaScript是在创建变量(对象、字符串等)时自动进行了分配内存,并且在不使用他们时“自动释放...

  • Java的垃圾回收机制是什么?

    顾名思义,垃圾回收就是释放垃圾占用的空间,那么在Java中,什么样的对象会被认定为“垃圾”?那么当一些对象被确定为垃圾之后,采用什么样的策略来进行回收(释放空间)?在目前的商业虚拟机中,有哪些典型的垃圾...

  • 看完后你会明白什么是垃圾回收机制

    不需要时将其释放回归:在不需要字符串、对象的时候,需要释放其所占用的内存,否则将会消耗完系统中所有可用的内存,造成系统崩溃,这就是垃圾回收机制所存在的意义。所谓的内存泄漏指的是:由于疏忽或错误造成程序...

  • 垃圾回收器ZGC应用分析总结

    主要总结ZGC关键技术与垃圾回收原理,并总结ZGC调优案例实践,以及业务升级JDK11与应用ZGC注意事项

  • gc垃圾回收机制

    二、jvm 垃圾回收(GC) 2.1 什么是垃圾回收 刚才我们学习了JVM的内存结构包括五大区域:程序计数器、本都方法区、栈内存、堆内存、方法区。 其中程序计数器、本地方法区、栈内存3个区域随线程而生、随线程而灭,...

  • 深入理解 Java 垃圾回收机制

    一:垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不在考虑内存管理。由于有个垃圾回收机制,java中的额...

  • 垃圾回收机制——GC详讲

    垃圾回收机制GC详讲

  • [JVM基础]-- 垃圾回收器

    垃圾回收器一、什么是垃圾回收器二、垃圾回收器的分类1.并行,串行,并发之间的区别1. Serial(串行收集器)2.ParNew3.Parallel Scavenge(1)降低停顿时间的两种方式(2)Parallel Scavenge提供的参数4.Serial Old5...

  • 深入理解 JVM 垃圾回收机制及其实现原理

    垃圾回收 通过上面的介绍,我们已经知道了什么是垃圾以及如何判断一个对象是否是垃圾。那么接下来,我们就来了解如何回收垃圾,这就是垃圾回收算法和垃圾回收器需要做的事情了。 垃圾回收算法 标记-清除算法 标记-...

  • GC垃圾回收机制

    垃圾回收是一种自动的存储管理机制。当一些被占用的内存不再需要时,将其释放,以让出空间,这种存储管理机制,就叫做垃圾回收机制。可以很大程度减轻程序员的负担和错误。 通常在堆(heap)和 元空间(metaspace)需要...

  • 关于前端垃圾回收机制详解

    垃圾回收 c一类的语言拥有底层的内存管理原语malloc()和free(), 而像javascript这样的高级语言,会自动释放内存,这一过程就是内存垃圾回收 虽然我们有自动的垃圾回收机制,依然会有内存管理的问题,例如内存泄露...

  • Java垃圾回收(GC)机制

    一、为什么要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。 哪些内存...

  • golang的垃圾回收详解

    作为一门现代化的语言,golang与java一样,都在语言中内置了垃圾回收的功能,不需要程序员自己去回收堆内存。而垃圾回收中,最重要的两个部分就是垃圾检测算法以及垃圾回收算法。垃圾检测算法决定哪些对象是垃圾需要...

  • [Java基础] 垃圾回收机制

    本文简单介绍一下Java的垃圾回收机制相关概念。

  • java list clear 垃圾回收_java垃圾回收机制

    1、什么是垃圾回收?程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导数内存溢出,所以内存资源的管是非常重要了。1.1、C/C++语言的垃圾回收在C/C++语言中,没有自动...

  • 垃圾回收机制,垃圾回收的几种方法以及

    什么是垃圾回收机制 垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。 内存泄露是指该内存空间使用完毕之后未回收,内存泄露过多会导致内存溢出,导致应用程序所占内存超出系统限制,最终被系统杀掉。 什么...

  • 深入理解Java虚拟机:Java垃圾回收机制

    本篇内容包括:JAVA 垃圾回收机制概述、有哪些内存需要回收、如何回收(标记-清除、标记-整理(标记-清除-压缩)、复制(标记-复制-清除)、分代收集等算法) 以及 何时进行垃圾回收等内容!

  • GC垃圾回收机制最全

    GC垃圾回收机制 GC概述 垃圾回收是一种自动的存储管理机制。 当一些被占用的内存不再需要时,就应该予以释放,以让出空间,这种存储资源管理,称为垃圾回收(Garbage Collection)。 1.为什么要有GC? GC是垃圾收集...

  • 什么是JAVA垃圾回收?

    转载自公众号 技术特工队在java中垃圾回收是系统自动完成的,了解它对优化应用程序有很大的帮助。那么我们就从下面几个方面来了解垃圾回收机制:哪些对象需要回收?什么时候回收?怎么去回收?判断对象可以回收的...

Global site tag (gtag.js) - Google Analytics