python垃圾回收与java比较_基于Java和Python的垃圾回收机制调研

1. 概述简要介绍本调研报告的主要内容,类似一篇文章的摘要

本篇调研报告主要围绕垃圾回收机制这个中心议题展开进行讨论。

首先,本文会阐述垃圾回收机制技术的背景和现行状态,其次介绍通有的一些垃圾回收机制概念和技术,然后以Java和Python语言的垃圾回收机制为例对垃圾回收机制进行实例化的阐述,以期读者能够有更好的认知。最后,本文将对各种典型常见的垃圾回收机制技术做一些总结性评价,以期读者能够获得一些有意义的结论。

2. 垃圾回收机制技术的背景及现状所讨论的技术的发展背景及现状等

众所周知,垃圾回收在编程语言程序运行过程中起到至关重要的作用,是一门重要的技术手段。

在高级程序设计语言的诞生初期,以C、C++为代表的编译型语言是当时的主流。这类语言通常具有指针变量、程序员主动申请、分配和回收内存等特征,这类机制在编写程序时确实提供了极大的灵活性,让程序员能够灵活地管理内存。但同时也带了一些比较严重的问题:内存泄漏、指针悬挂等Bug就是由于这类机制存在而经常发生,给程序带来了比较高的安全隐患。

而随着高级程序设计语言的发展和进步,以面对对象为主要思想、脱离具体架构的Java语言和灵活简单的脚本式语言Python等逐步出现。在这种背景下,由于降低程序编写难度、简化操作的要求,底层的内存管理不再成为一个重要问题,而这时设计者就开始寻找程序自动管理内存的方法和机制,垃圾回收机制就是这样背景下的、为解决该类问题而生的技术产物。

所谓垃圾,就是那些在程序运行过程中不再有使用需求的对象、数据结构等,而这些对象、数据结构仍会占据系统内存,造成内存浪费,因此被称为‘“垃圾”。而垃圾回收技术,就是利用算法程序自动化识别回收整理这些垃圾,以保证程序充分的空间性能。

当今的垃圾回收技术已经发展的较为复杂和稳定,垃圾回收程序往往会不定时地运行,往往会在CPU空闲或内存空间不足时进行垃圾回收操作。目前大部分主流的高级程序设计语言都有对应的垃圾回收机制和策略,包括Java、Python、PHP和Ruby等等。

可以说,垃圾回收技术已经成为了优化程序性能,提高程序稳定度的一项重要技术,在当今的程序设计和底层支撑中发挥着非常重要的作用。

3. 垃圾回收机制分析该技术涉及的相关技术、项目、案例、应用等进行介绍和分析

可根据内容需要自行决定分更多章节;如需更多章节,则后续章节编号顺延

3.1 整体描述

垃圾回收机制的基本任务有两个:找到所有存活对象(剩下的就是垃圾)

回收被无用对象占用的内存

因此,垃圾回收程序的设计目标就非常明确了。我们首先要识别出那些占用内存的成员是垃圾可以进行回收,然后对这些垃圾进行内存回收的操作。其中应当关注的重点应当是算法的时间和空间复杂度,要尽可能地把垃圾回收程序对程序本身的影响降到最低,这才是一个比较优秀的垃圾回收算法。在垃圾回收机制中,不同的策略往往有其不同的优势,我们往往通过结合多种方法,将每种方法放置在适用的情境下进行使用,往往能取得最好的效果。

3.2 垃圾判断算法

垃圾判断算法的目标很简单,就是判断找出无用的且占内存空间的变量。目前常用的算法有两种:引用计数法和根搜索算法。

3.2.1 引用计数法

引用计数法的思想非常简单:那就是在整个程序的生命周期中统计每个占用变量被引用了多少次(计数)。当一个变量的引用数为0时,就可以视该变量为无用的垃圾,可以进行回收。

引用计数法将时间和运行成本平均分摊到整个程序运行过程中,这样避免了局部性问题,平均了性能表现,这样对于实时运行环境非常有利,尤其适用于边解释边执行的脚本类语言。

但其较为严重的缺陷在于无法检测出循环引用的变量,如果两个或多个变量进行循环引用,那么计数就无法判断出这些变量是垃圾,反而认为他们都是有用的变量。因此这是在引用计数法中急需注意的一点,我们常常辅以其他解决手段进行解决。

3.2.2 根搜索算法

另一种主流的垃圾判断算法是根搜索算法。所谓的跟搜索算法,就是从根节点开始搜索,遍历所有的变量,用排除法找到垃圾。其中的根集,指的是正在执行的程序可以访问的引用变量的集合。通过找到这些变量,我们可以从这些变量出发,遍历以找到所有的被引用的变量依赖,在这个过程中我们又能确保这些遍历到的变量确实是真的“有用”变量而不是垃圾。该算法的数学原理为图论,那些循环变量和孤立的垃圾变量会被孤立到被引用的根集图之外以被识别出来,因此巧妙地避免了循环引用的问题。

该算法的优点就是避免了引用依赖的问题,同时可以灵活的安排垃圾回收程序运行的时机。因为是一次性回收,不像引用计数法在整个执行过程中回收,因此可以在CPU空闲以及内存空间不够时按需回收,这样极大地增加了垃圾回收的灵活性。

3.3 回收垃圾对象算法

回收垃圾对象的算法目标是对识别出的无用垃圾变量进行回收,而如何高效的回收,并且回收结果能更好地服务后续操作,则是该算法所面对的核心问题。

3.3.1 标记-清除算法

标记-清除算法非常简单,就是在识别垃圾后对内存进行直接回收,不去做多余的操作。该方法的原理非常简单,但是存在的较大问题是会导致出现大量的内存碎片,不利于后续的程序运行,导致内存浪费严重。因此该方法不是回收垃圾对象算法的主流方法。

3.3.2 标记-整理算法

标记-整理算法是另一主流的的回收垃圾对象的算法,其主要思想和标记-清除算法相似,也是对标记的垃圾进行直接回收,但最大的不同在于:每次回收之后,会进行剩余对象的移动,以填补回收后形成的空缺,这样就避免了标记-清除算法中造成的内存碎片问题。而该算法的缺点也就相应地暴露了出来,当进行这样的移动操作时,自然就避免不了了更大的时间和性能开销。

3.3.3 Copy算法

该算法结合了前两种回收垃圾算法的优势,首先先划定一块事先约定好的空间(可以是可用内存区域的一般或四分之一),然后在这一半上进行标记-清除式的回收。当该部分内存不足时(碎片过多),就使用标记-整理的方法将该区域的所有变量移动至另一块内存中,在此移动过程中对内存碎片做整理,就避免了内存碎片的情况。该算法带来的一大缺陷是:由于划分了内存,因此在初期使用内存的时候可能会面临内存不足的情况。因此,根据该算法的特点,整体来说该算法效率较高,但是不适用于生命周期较长的对象,因为如果大部分对象都是生命周期较长的对象,那么将浪费大量的时间在长周期对象中。

3.4 Java垃圾回收机制

该部分对实际的Java的GC算法做简单的阐述说明,进一步阐明垃圾回收在实际中的运用情况。Java的GC过程中对垃圾的处理算法并不是单一的,充分考虑了性能原因,Java设计了多种策略结合的GC算法。

首先,垃圾判断算法方面,Java纯粹使用了根搜索算法来做垃圾识别,由于深刻的面对对象机制,Java对对象的循环引用问题非常重视,因此直接摒弃掉了无法解决循环引用问题的引用计数法,使用了单一的跟搜索算法(也称为可达性分析)

其次,在垃圾回收算法方面,Java使用了较为复杂的机制,其中最具代表性的,就是Java的分代回收机制。

在Java中,会把对象分为三类:新生代、老年代、持久代。首先,新生代就是指在运行时生命周期不是特别长的变量对象,新生代的变量往往在新生代专属的内存区域存活。这里的垃圾回收算法主要是使用Copy算法,当经过一轮垃圾回收之后,原本在Eden区的所有的存活对象会被转移至From区。而在当From区也满了的时候,就会再次执行垃圾回收操作,将Eden和From区内存活的所有对象移动至To区内,然后该To区就变成了From区,完成了互换。在程序运行时,会不断重复这样的操作,而当To区也不足以存储From区和Eden区所存活的对象时,就会就会将存活对象放到老年代所在的区域。进入老年代区域后,GC器会对该区域施行清除-整理算法式的回收,而当老年代内存也满了的时候,就会触发GC器进行一次全局的GC。

持久代常常来储存一些程序运行时的变量,在Java8及以后JVM移除了这一区域,将常量保存到了其他区域。

3.5 Python垃圾回收机制

Python的垃圾回收机制与Java还是存在着不小的差异的。首先在垃圾识别算法上,Python采用引用计数为主的操作方法。

Python使用引用计数为主的垃圾识别算法最关键的原因,在于Python是解释执行的脚本式语言。解释型的语言最大的特点是边解释,便执行,因此进行同步的对象引用计数操作就是顺利成章的事情了,能将计算分摊到整个程序运行的生命周期中,一旦对象没有引用后进行直接回收,整个程序收到的压力便会小很多,很适于脚本式语言的运行。但带来最显著的问题,就是极大的拖慢了程序运行的速度,因此我们不会对脚本类的语言性能有太高的要求。

同时,为了解决循环依赖问题,Python语言使用另一种机制来辅助监测循环依赖情况。Python针对可能产生循环引用情况的变量,创造了两个链表:root链表和unreachable链表。root链表中存储被使用的变量对象,而unreachable链表负责存储即将被回收的“垃圾”变量对象。之所以这样做,是考虑到被放入unreachable链表内的对象还有被其他变量间接或直接引用的可能,如果被引用,则移入root链表内,然后对剩下的unreachable的变量进行回收。

同时,在Python中也有分代回收机制,也主要是针对非即时回收的变量,但简单很多。Python往往会维护三个代的链表012,0代对象在第一次GC中存活,则移入1代,1代对象存活,再次经过GC存活,则移入2代。Python会对每代的GC时机设定阈值,当前一代的垃圾回收次数超过当前代的阈值,就会触发一次本代的垃圾回收,以最终实现垃圾回收的分代回收。

4. 总结

通过对垃圾回收机制的了解,我们发现,垃圾回收算法所实现的基本任务无非是垃圾监测+释放。通过这两步基本操作,我们就能实现对无用变量占用内存的回收,保证程序执行的效率。

而在这个过程中,如何高效地回收,平衡时间和空间复杂度,让整个程序在回收过程中也保持着较好的性能,就是我们在设定垃圾回收机制规则时所需要着重思考的问题。而解决该问题往往也需要具体问题具体分析,针对不同程序语言的特性,针对不同程序运行阶段的特点,为其针对性的设置垃圾回收方法,以此才能达到令人满意的效果。

垃圾回收机制往往并不会存在在编译过程中,垃圾回收的操作更多地存在在程序动态运行的时候,作为一种辅助监测机制来进行监测。而在编译过程中,我们也可以进行编译层面的垃圾回收机制,可以根本不去初始化一些根本未被使用过的变量对象,以节省程序运行占用的内存等等,但最重要的垃圾回收还是在程序运行时进行的。

5. 参考文献所参考的期刊文章、书、网站文章等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值