GC是什么?为什么我们要去使用它
GC(Garbage Collection)是各大语言的宠儿,也是计算机科学领域里很热门的一个话题。最早在JVM中有看过这个算法,后来发现即使是js这种脚本语言也是有GC的。单纯就JVM来说的话,GC算法也在不断地改进,成熟。从最早的串行到高顿吞吐量的并行,为了解决高延迟又演化出了CMS(Concurrent Mark Sweep),为了解决碎片的问题,又开发了G1.
为什么我们需要进行GC呢
在早期的编程语言中,程序运行中没有栈帧(Stack Frame)去维护,所以采用的是静态分配策略,这比动态分配要快不少,但是它有一个很不人性化的缺点就是需要在编译期的时候确定程序所需要的数据结构大小。
在1958年,Algol-58 语言首次提出了块结构(block-structured),块结构语言通过在内存中申请栈帧来实现按需分配的动态策略。在过程被调用时,帧(frame)会被压到栈的最上面,调用结束时弹出。栈分配策略赋予程序员极大的自由度,局部变量在不同的调用过程中具有不同的值,这为递归提供了基础。但是后进先出(Last-In-First-Out, LIFO)的栈限制了栈帧的生命周期不能超过其调用者,而且由于每个栈帧是固定大小,所以一个过程的返回值也必须在编译期确定。所以诞生了新的内存管理策略——堆(heap)管理。
现在计算机VS图灵机
现代计算机相对于图灵机来说,本质上的区别就在于资源有限性,所以在使用完各种资源以后,需要将其释放(release)。
那释放资源全都用GC可以嘛
GC本来就是给马大哈的程序员准备的,人为的手动释放资源很容易出问题,那我能不能在每次需要释放资源的时候都调用GC算法呢?这样不是一劳永逸嘛。
并不能,GC同样有它适用的和不适用的场景,在(socket/file handle)的使用中没有使用GC,很大一部分原因在于它的不确定性。你即使调用了GC你也不知道它啥时会回收,它到底会不会回收,这样的GC还是不可靠(雾,GC都是大猪蹄子
但是如果我们显示对资源进行回收就不一样了,调用了close/destroy后,资源百分百就被释放掉了
为啥在内存里面就可以用GC呢,有两个原因,第一是它具有独占性(当然你也可以叫唯一性)OS给每个运行的程序分配的内存都是唯一的,也是相互独立的,咋俩互不干扰,我晚一点回收对你也没有什么影响。第二点是内存够用,日常使用程序中也没见内存占用太高,我晚一点回收也不会OutOfMenmory,那我就放心大胆地用GC的回收机制。
由这两点可见,对于资源比较紧张的一些嵌入式的设备,还是手动释放资源来的较好。(不包括树莓派)
GC是什么
GC的本质是内存的自动管理,用来回收堆(Heap)中不再需要(使用)的对象。
我们知道内存其实也会被划分为各个区域的,常见的stack和heap。stack里面装的是局部变量,函数的调用结束以后也就回收了,这个是个固定的流程,所以不需要GC。Heap中的空间,用来在多个函数之间去共享数据,由程序自己来动态申请,这个时候我们就需要利用到GC了
GC由两大核心组成
- 对象识别,其实也就是常说的判断对象是否存活,live object和garbage
- 回收算法,什么时候回收,如何回收
那咋办嘛
先从对象识别开始说下吧,判断对象是live object还是garbage
在堆(Heap)里存放着Java中基本上所有对象的实例,当一个对象没有引用且不会再引用的时候就可以认为他已经死去,视为garbage
引用计数(Python和PHP都采用这种方式)
给对象一个引用计数器(在对象头加上一个counter),当引用的时候计数器就加一,引用失效就减一,引用次数为0的时候,该对象就失效了。
这个很像OS里面的PV原语,实现是很简单的,效率也比较高。但缺点也是显而易见的,就是很难去解决对象之间循环使用的问题。
举个栗子 如果现在有两个对象 OA OB ,OA.instance = OB;OB.instance=OA;它们两个相互引用,导致counter都不为0,于是都不会被回收
可达性分析(Tracing)
这个是现代语言使用最广泛的一种方式,从root对象开始,不断的去追踪(tracing),找到所有可以被引用的对象,那这些对象就可以被称作是可达的(reachable),剩下的对象自然就是不可达对象,视作garbage将其回收。
那么,你说的这个root对象,它是什么样子的呢?
- Java 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 本地方法栈中引用的对象
- 方法区中常量引用的对象
- 方法区中类静态属性引用的对象
被堆中对象所引用的对象,它们就不算Roots了,这样就不会引起循环引用的问题。
引用
判定对象是否存活与“引用”有关。在 JDK 1.2 以前,Java 中的引用定义很传统,一个对象只有被引用或者没有被引用两种状态,我们希望能描述这一类对象:当内存空间还足够时,则保留在内存中;如果内存空间在进行垃圾手收集后还是非常紧张,则可以抛弃这些对象。很多系统的缓存功能都符合这样的应用场景。
在 JDK 1.2 之后,Java 对引用的概念进行了扩充,将引用分为了以下四种。不同的引用类型,主要体现的是对象不同的可达性状态reachable和垃圾收集的影响。
强引用(Strong Reference)
类似 "Object obj = new Object()" 这类的引用,就是强引用,只要强引用存在,垃圾收集器永远不会回收被引用的对象。但是,如果我们错误地保持了强引用,比如:赋值给了 static 变量,那么对象在很长一段时间内不会被回收,会产生内存泄漏。
软引用(Soft Reference)
软引用是一种相对强引用弱化一些的引用,可以让对象豁免一些垃圾收集,只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象。JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用通常用来实现内存敏感的缓存,如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。
弱引用(Weak Reference)
弱引用的强度比软引用更弱一些。当 JVM 进行垃圾回收时,无论内存是否充足,都会回收只被弱引用关联的对象。
虚引用(Phantom Reference)
虚引用也称幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响。它仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制,比如,通常用来做所谓的 Post-Mortem 清理机制。
事实上,软引用,弱引用和虚引用都可以被叫做弱引用
以弱引用的方式指向一个对象,弱引用不会保护该对象被 GC 回收。如果该对象被回收了,那么这个弱引用会被赋予一个安全值(一般为NULL)。
可以看一下这个wiki,讲了一下弱引用如何解决循环引用Dealing with reference cycles
参考
- A Beginner’s Guide to Garbage Collection
- 垃圾回收策略和算法
- 深入浅出垃圾回收
- https://cs.stackexchange.com/questions/52735/why-does-garbage-collection-extend-only-to-memory-and-not-other-resource-types
GC是什么?为什么我们要去使用它的更多相关文章
- [译]GC专家系列1: 理解Java垃圾回收
原文链接:http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/ 了解Java的垃圾回收(GC)原 ...
- Java GC专家系列1:理解Java垃圾回收
了解Java的垃圾回收(GC)原理能给我们带来什么好处?对于软件工程师来说,满足技术好奇心可算是一个,但重要的是理解GC能帮忙我们更好的编写Java应用程序. 上面是我个人的主观的看法,但我相信熟练掌 ...
- JVM性能调优,GC
刚刚做完了一个项目的性能测试,“有幸”也遇到了内存泄露的案例,所以在此和大家分享一下. 主要从以下几部分来说明,关于内存和内存泄露.溢出的概念,区分内存泄露和内存溢出:内存的区域划分,了解GC回收机制 ...
- JVM GC 机制与性能优化
目录(?)[+] 1 背景介绍 与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理.JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自 ...
- GC(Garbage Collection)垃圾回收机制
1.在垃圾回收器中,程序员没有执行权,只有通知它的权利. 2.程序员可以通过System.gc().通知GC运行,但是Java规范并不能保证立刻运行. 3.finalize()方法,是java提供给程 ...
- GC回收算法
GC回收算法 https://www.cnblogs.com/missOfAugust/p/9528166.html Java语言引入了垃圾回收机制,让C++语言中令人头疼的内存管理问题迎刃而解,使得 ...
- GC回收算法--当女友跟你提分手!
Java语言引入了垃圾回收机制,让C++语言中令人头疼的内存管理问题迎刃而解,使得我们Java狗每天开开心心地创建对象而不用管对象死活,这些都是Java的垃圾回收机制带来的好处.但是Java的垃圾回收 ...
- Lua GC机制
说明 分析lua使用的gc算法,如何做到分步gc,以及测试结论 gc算法分析 lua gc采用的是标记-清除算法,即一次gc分两步: 从根节点开始遍历gc对象,如果可达,则标记 遍历所有的gc对象,清 ...
- 浅谈 JVM GC 的安全点与安全区域
OopMap 前文我们说到,JVM 采用的可达性分析法有个缺点,就是从 GC Roots 找引用链耗时. 都说他耗时,他究竟耗时在哪里? GC 进行扫描时,需要查看每个位置存储的是不是引用类型,如果是 ...
- .NET CoreCLR开发人员指南(上)
1.为什么每一个CLR开发人员都需要读这篇文章 和所有的其他的大型代码库相比,CLR代码库有很多而且比较成熟的代码调试工具去检测BUG.对于程序员来说,理解这些规则和习惯写法非常的重要. 这篇文章让所 ...
随机推荐
- C#—使用InstallerProjects打包桌面应用程序
前言 打包桌面应用程序实在是一个不常使用的东西,偶尔使用起来经常会忘东忘西的耽误时间,因此,这篇文章多以图片记录过程,也是用于备忘. 下载打包工具 C#打包桌面应用程序有很多种方法,这里介绍一种使用M ...
- BFS(二):数的变换
[例1]整数变换(POJ 3278 “Catch That Cow”) 给定两个整数a和b(0 ≤a,b≤100,000),要求把a变换到b.变换规则为:(1)当前数加1:(2)当前数减1:(3)当前 ...
- 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数 例如给定nums = [2,7,11,15],target = 9
python解决方案 nums = [1,2,3,4,5,6] #假如这是给定的数组 target = 9 #假如这是给定的目标值 num_list = [] #用来装结果的容器 def run(nu ...
- 仿照Spring自己实现有各种通知的AOP,AOP实现的步骤分解
一.需求: 仿照Spring的AOP写的 MyAOP 2.0,有环绕通知.前置通知.后置通知.返回通知.异常通知等. 已实现:①通过动态代理+通知的注解类,实现了前置通知.后置通知等各种通知:②切点( ...
- Codeforces Gym101518H:No Smoking, Please(最小割)
题目链接 题意 给出一个n*m的酒店,每个点是一个房间,要将这个酒店的房间划分成为两块(一块无烟区,一块吸烟区),相邻的两个房间之间有一条带权边,权值代表空气锁的面积,如果把这条边给去掉,那么需要花费 ...
- BZOJ 1483:[HNOI2009]梦幻布丁(链表启发式合并)
http://www.lydsy.com/JudgeOnline/problem.php?id=1483 题意:中文. 思路:对于每一种颜色,用一个链表串起来,一开始保存一个答案,后面颜色替换的时候再 ...
- js 为何范围内随机取整要用floor,而不是ceil或者round呢
壹 ❀ 引 我在如何使用js取任意范围内随机整数这篇博客中,列举并分析了取[n,m)与[n,m]范围内整数的通用方法,并在文章结果留了一个疑问:为什么通用方法中取整操作,我们使用Math.floor ...
- 基于SpringBoot从零构建博客网站 - 设计可扩展上传模块和开发修改头像密码功能
上传模块在web开发中是很常见的功能也是很重要的功能,在web应用中需要上传的可以是图片.pdf.压缩包等其它类型的文件,同时对于图片可能需要回显,对于其它文件要能够支持下载等.在守望博客系统中对于上 ...
- Linux系统下word转pdf,xls转pdf,ppt转pdf
word转换pdf的技术方案,供参考.[doc/docx/ppt/pptx/xls/xlsx均支持转换] 本方案是Java结合shell命令完成,不同于以往的仅依赖java组件转换 ...
- Bzoj 3654 图样图森波 题解
3654: 图样图森破 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 123 Solved: 66[Submit][Status][Discuss] ...