Java 和 PHP GC 的差异和差异出现的原因

这篇具有很好参考价值的文章主要介绍了Java 和 PHP GC 的差异和差异出现的原因。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 JAVA 的 GC 处理

判断草死掉的两种方式:引用计数和可达性分析

可达性分析对 JAVA 比较好用的原因是 JAVA遵守这面向对象的严格要求,每个变量都被对象包裹,所以每个变量都能通过对象来进行遍历找到,最终判断他们的是否被引用;

但对于 PHP 这类面向过程下构建的面向对象,找变量引用就比较零碎了,所以主要是引用计数为主;

便捷记忆,在一片空地上,死掉的草都清理(标记清除),就会出现零碎的光秃点,随着秃点增多,将不是秃点的草都挪到新的空地(复制),这样腾出的地和秃点合在一起形成新的空地,有些草活得比较久,有些草活得短,根据查看的频次将活得短的聚合在一起,活得长的聚合在一起,就是分代算法

Java的垃圾回收(Garbage Collection,GC)机制是一种自动管理内存的技术,它负责检测和清理不再被引用的对象,以释放内存并防止内存泄漏。在Java中,开发人员无需手动释放内存,因为这是由垃圾回收器自动完成的。Java的垃圾回收机制主要基于以下两个原则:

  1. 引用计数(Reference Counting):这是一种简单的垃圾回收方法,它通过跟踪每个对象的引用计数来确定对象是否可以被回收。当引用计数为零时,对象被认为是不再被引用的,可以被回收。然而,这种方法容易出现循环引用问题,因此在Java中并没有广泛使用。

  2. 可达性分析(Reachability Analysis):这是Java主要使用的垃圾回收方法。它从根对象(如主方法中的局部变量和静态变量)开始,通过引用链追踪对象是否可以被访问。如果一个对象不再通过任何引用链与根对象相连,那么这个对象就被认为是不可达的,可以被回收。

以下是Java中几种主要的垃圾回收算法:

  1. 标记-清除算法(Mark and Sweep)

    • 这是最基本的垃圾回收算法。
    • 首先,它通过可达性分析标记所有可达对象。
    • 然后,它扫描整个堆,清理未标记的对象。
    • 这个算法的问题是会产生内存碎片,可能会导致堆内存不连续,进而影响程序性能。
  2. 复制算法(Copying)

    • 这个算法将堆内存分为两个区域:一半是已使用的区域,一半是空的。
    • 它首先在已使用区域进行标记,然后将存活的对象复制到空区域,最后清理已使用区域。
    • 这个算法的优点是避免了内存碎片问题,但需要额外的内存用于复制对象。
  3. 标记-整理算法(Mark and Compact)

    • 这个算法结合了标记-清除和复制算法的优点。
    • 首先,它标记可达对象,然后将它们压缩到堆的一端,清理掉堆的另一端的垃圾对象。
    • 这个算法也可以减少内存碎片,但不需要额外的内存。
  4. 分代算法(Generational)

    • 这个算法根据对象的年龄将堆分成不同的代。
    • 年轻代中的对象通常具有较短的生命周期,老年代中的对象具有较长的生命周期。
    • 垃圾回收频繁地发生在年轻代,而较少发生在老年代。
    • 这个算法利用了对象的特性,提高了回收效率。

PHP 的 GC 处理

PHP 使用引用计数(Reference Counting)作为主要的垃圾回收机制。每个变量和对象在 PHP 中都有一个引用计数器,用于跟踪对象的引用关系。当一个变量或对象的引用计数降为零时,它就会被认为是不再被引用的,可以被垃圾回收。

以下是 PHP 引用计数垃圾回收机制的基本工作原理:

  1. 引用计数:每当一个变量或对象引用另一个变量或对象时,引用计数会增加1。当一个变量不再引用某个对象时,引用计数会减少1。这个计数器是实时更新的,反映了对象的当前引用情况。

  2. 回收不可达对象:垃圾回收器会定期检查引用计数,并找出那些引用计数为零的对象。这些对象被认为是不再被引用的,可以安全地回收内存。

  3. 循环引用问题:引用计数垃圾回收机制对于循环引用问题并不十分有效。循环引用是指一组对象互相引用,导致它们的引用计数永远不会降为零。为了解决这个问题,PHP 引入了周期性垃圾回收(Cycle Collector),它定期检测并处理循环引用。

  4. 周期性垃圾回收:周期性垃圾回收器负责检测循环引用,并释放被这些循环引用困住的内存。它会在特定的时间间隔内运行,识别并处理循环引用,从而防止内存泄漏。

Python 的 GC 处理

 

Python 的垃圾回收(Garbage Collection,GC)机制主要基于引用计数和循环垃圾回收两个核心原理,以自动管理内存。以下是 Python 的垃圾回收机制的详细说明:

  1. 引用计数(Reference Counting)

    • Python 中的每个对象都有一个引用计数器,用于跟踪对象的引用关系。
    • 当一个对象被引用时,其引用计数会增加1,当一个对象不再被引用时,其引用计数会减少1。
    • 当引用计数降为零时,说明对象不再被任何变量或数据结构引用,可以被垃圾回收。
  2. 循环垃圾回收

    • 引用计数机制可以有效地处理大多数情况,但对于循环引用(两个或多个对象相互引用形成环)的情况无法处理。
    • 为了解决循环引用问题,Python 引入了循环垃圾回收器(Cycle Collector)。
    • 循环垃圾回收器定期检查引用关系图,找出并清理不可达的循环引用。
  3. 分代垃圾回收

    • Python 的垃圾回收还引入了分代垃圾回收策略,将对象分为三代:年轻代、中年代和老年代。
    • 大部分新创建的对象放入年轻代,如果在几轮垃圾回收后仍然存活,它们会晋升到中年代,然后到老年代。
    • 基于分代的策略利用了对象的生命周期模式,提高了垃圾回收的效率。
  4. 垃圾回收周期

    • Python 的垃圾回收不是持续运行的,而是在特定条件下触发。
    • 垃圾回收器会在一组触发条件满足时运行,如年轻代中对象的数量超过阈值、内存分配请求失败等。
    • 当触发条件满足时,垃圾回收器会进行一轮或多轮垃圾回收,清理不可达对象。
  5. gc 模块

    • Python 提供了一个名为 gc 的模块,用于手动控制和配置垃圾回收机制。
    • 开发人员可以使用 gc 模块中的函数来手动触发垃圾回收、禁用垃圾回收或配置垃圾回收参数。

PHP GC 和 Python GC 的差异

PHP 和 Python 是两种不同的脚本语言,它们的垃圾回收(GC)算法和策略存在一些差异。以下是 PHP 和 Python 的 GC 算法之间的主要区别:

PHP 的 GC 算法

  1. 引用计数:PHP 主要使用引用计数来管理内存。每个变量和对象都有一个引用计数,当引用计数变为零时,变量或对象就被回收。这个方法简单且实时,但容易出现循环引用问题。

  2. 周期性垃圾回收:为了解决循环引用问题,PHP 引入了周期性垃圾回收(Cycle Collector)。周期性垃圾回收器会定期检查对象之间的引用关系,以便释放不再使用的内存。这是 PHP 针对循环引用问题的一种补救措施。

  3. Zend Memory Manager:PHP 使用 Zend Memory Manager 来管理内存。它负责内存分配和释放,以及跟踪引用计数和垃圾回收。Zend Memory Manager 可以通过配置参数来调整垃圾回收行为。

Python 的 GC 算法

  1. 引用计数和循环垃圾回收:Python 同样使用引用计数来追踪对象的引用关系。但与 PHP 不同,Python 还实现了循环垃圾回收器,用于检测并处理循环引用。

  2. 分代垃圾回收:Python 的垃圾回收还引入了分代垃圾回收策略。Python 将对象分为三代:年轻代、中年代和老年代。新创建的对象会放入年轻代,如果经过一定数量的垃圾回收循环后仍然存活,它们会被提升到中年代,以此类推。这个策略利用了观察到的对象生命周期模式,提高了垃圾回收的效率。

  3. 垃圾回收周期:Python 的垃圾回收器不是定期运行的,而是基于阈值和触发条件来触发的。具体触发条件包括年轻代对象数量、年轻代空间占用率等。这个策略可以降低垃圾回收对性能的影响。

GO 语言的 GC

Go语言(或简称Golang)的垃圾回收(GC)是一种自动管理内存的机制,旨在减轻开发人员手动管理内存的负担,提高程序的可靠性和性能。Go语言的GC机制具有以下特点和原则:

  1. 并发垃圾回收:Go语言的GC是并发的,这意味着垃圾回收器可以在程序运行的同时执行。它不会导致应用程序停顿(Stop-The-World),因此对于高并发和实时性要求高的应用程序非常适用。

  2. 分代垃圾回收:Go语言的GC使用分代垃圾回收策略,将堆内存分为三代:新生代、中年代和老年代。新分配的对象通常放入新生代,存活时间较长的对象会升级到中年代和老年代。这种分代策略提高了垃圾回收的效率。

  3. 标记-清除算法:Go语言的垃圾回收器使用标记-清除(Mark-and-Sweep)算法。它首先标记所有活动对象,然后清除未标记的对象。这个算法能够处理循环引用并有效地回收不再使用的内存。

  4. 三色标记法:Go语言的GC引入了三色标记法,将对象标记为白色、黑色和灰色。黑色表示已经标记为活动对象,白色表示未标记的对象,灰色表示待处理的对象。这个方法有助于减少标记和清除的阶段。

  5. 垃圾回收时间控制:Go语言的垃圾回收器可以通过设置环境变量来控制垃圾回收的时间和频率。这使得开发人员可以根据应用程序的需求进行调整,以平衡性能和内存使用。

  6. 内存分配优化:Go语言的运行时系统还包括了一个内存分配器,它针对小对象和大对象进行了优化,以减少内存碎片和提高分配性能。

都有哪些场景会用到循环引用?

循环引用是指两个或多个对象之间相互引用,形成一个环形的引用关系。这种情况通常不是有意为之,而是一种错误或者设计不当的情况。尽管循环引用通常是不推荐的,但有一些特定的情景可能需要它们,尤其是在某些编程模型或设计中:

  1. 数据结构中的循环引用:在某些数据结构中,循环引用是有意为之的。例如,双向链表中的每个节点都包含对前一个和后一个节点的引用,因此它们会形成一个环形引用。这种数据结构在某些情况下非常有用。

  2. 图数据结构:图是由节点和边组成的数据结构,其中节点之间可能存在循环引用。图数据结构通常用于表示网络、关系和复杂的数据关联。在这种情况下,循环引用是必要的。

  3. 观察者模式:在观察者模式中,主题对象(Subject)和观察者对象(Observer)之间可能存在循环引用。主题对象需要通知观察者对象进行更新,而观察者对象通常也需要引用主题对象以便取消注册。这种情况下,循环引用是合理的。

  4. 资源管理:某些资源需要引用它们的持有者。例如,一个对象可能需要引用一个打开的文件、数据库连接或网络连接。这种情况下,资源可能会被多个对象持有,形成循环引用,以确保在没有对象引用资源时不会被关闭。

Javascript 循环引用的一个案例

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  notify(message) {
    this.observers.forEach(observer => {
      observer.update(message);
    });
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }

  update(message) {
    console.log(`${this.name} received message: ${message}`);
  }
}

const subject = new Subject();
const observer1 = new Observer("Observer 1");
const observer2 = new Observer("Observer 2");

subject.addObserver(observer1);
subject.addObserver(observer2);

observer1.subject = subject; // 主题引用了观察者
observer2.subject = subject;

subject.notify("Hello, observers!");

在观察者模式中,观察者通常引用主题对象是为了实现以下目的:

  1. 访问主题数据:观察者需要访问主题对象的数据或状态以执行相应的操作。通过引用主题对象,观察者可以轻松地获取主题的信息。

  2. 响应主题的变化:观察者的主要任务是响应主题对象的状态变化。通过引用主题对象,观察者可以注册自己,并接收主题的通知,从而知道何时以及如何更新自己。

  3. 与主题建立松耦合关系:引用主题对象有助于观察者与主题对象之间建立松耦合的关系。观察者不需要了解主题对象的内部实现细节,只需关注主题的状态变化即可文章来源地址https://www.toymoban.com/news/detail-709386.html

到了这里,关于Java 和 PHP GC 的差异和差异出现的原因的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java JVM中的GC机制详解

    垃圾回收(Garbage Collection,简称GC)机制是JVM中最重要的部分之一。在Java程序运行的过程中,运行时数据区域(包括堆和栈等内存区域)一直都需要使用和回收内存空间。由于Java中的内存分配方式是动态的,所以在程序运行期间,其内存空间的占用量会不断变化。 如果Java程

    2024年02月14日
    浏览(42)
  • 分别用JavaScript,Java,PHP,C++实现桶排序的算法(附带源码)

    桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点: 在额外空间充足的情况下,尽量增大桶的数量 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中 同时,对于桶中

    2024年02月22日
    浏览(49)
  • JVM | 垃圾回收器(GC)- Java内存管理的守护者

    在编程世界中, 有效的内存管理 是至关重要的。这不仅确保了应用程序的稳定运行,还可以大大提高性能和响应速度。作为世界上最受欢迎的编程语言之一,通过Java虚拟机内部的垃圾回收器组件来自动管理内存,是成为之一的其中一项必不可少的技术点。 在许多传统的编程

    2024年02月09日
    浏览(53)
  • Java线上故障排查(CPU、磁盘、内存、网络、GC)+JVM性能调优监控工具+JVM常用参数和命令

    根据服务部署和项目架构,从如下几个方面排查: (1)运用服务器:排查内存,cpu,请求数等; (2)文件图片服务器:排查内存,cpu,请求数等; (3)计时器服务器:排查内存,cpu,请求数等; (4)redis服务器:排查内存,cpu,连接数等; (5)db服务器:排查内存,cpu,连接数

    2024年02月07日
    浏览(67)
  • java---垃圾回收算法(GC)

    目录 一、如何判断一个对象是否存活 1.引用计数法 2.可达性分析法 二、垃圾回收算法 1.标记清除法 2.复制算法 3.标记整理法 4.分代算法 具体流程 注意事项 空间分配担保原则 总结 Java 堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象

    2024年02月05日
    浏览(37)
  • JVM 内存和 GC 算法

    对象头(Header) 运行时元数据(Mark word):哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳 类型指针 :指向类元数据,确定对象所属类型。如果是数组还要记录数组的长度 实例数据(Instance Data):类中的各类型变量以及父类的相关类型数据。

    2024年02月05日
    浏览(39)
  • JVM GC 算法原理概述

    对于JVM的垃圾收集(GC),这是一个作为Java开发者必须了解的内容,那么,我们需要去了解哪些内容呢,其实,GC主要是解决下面的三个问题: 哪些内存需要回收? 什么时候回收? 如何回收? 回答了这三个问题,也就对于GC算法的原理有了最基本的了解。 1 如何判定哪些内

    2024年02月03日
    浏览(42)
  • java程序出现乱码的原因

    Java程序出现乱码的原因有以下几种可能 : 编码不一致 :Java程序使用的编码与当前系统或其他应用程序使用的编码不一致,导致字符无法正确显示。 字符集不支持 :Java程序使用的字符集不支持某些特殊字符或语言,导致这些字符无法正确显示。 数据库编码不一致 :Java程

    2024年02月08日
    浏览(30)
  • GC 三色标记算法(Go & Java版本)

    GC全称Garbage Collection,目前主流的垃圾回收算法有两类,分别是追踪式垃圾回收算法(Tracing garbage collection)和引用计数法( Reference counting )。 而三色标记法是属于追踪式垃圾回收算法的一种。追踪式算法的核心思想是判断一个对象是否可达,因为一旦这个对象不可达就可以

    2024年02月05日
    浏览(32)
  • JVM学习 GC垃圾回收机制 (堆内存结构、GC分类、四大垃圾回收算法)

    🤖 作者简介: 努力的clz ,一个努力编程的菜鸟 🐣🐤🐥   👀 文章专栏: 《JVM 学习笔记》 ,本专栏会专门记录博主在学习 JVM 中学习的知识点,以及遇到的问题。   🙉 文章详情: 本篇博客是学习 【狂神说Java】JVM快速入门篇 的学习笔记,关于 GC垃圾回收机制 (堆内存结

    2023年04月19日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包