千家信息网

PHP的垃圾回收机制相关知识点整理

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容主要讲解"PHP的垃圾回收机制相关知识点整理",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"PHP的垃圾回收机制相关知识点整理"吧!PHP目前的开发
千家信息网最后更新 2026年11月02日PHP的垃圾回收机制相关知识点整理

本篇内容主要讲解"PHP的垃圾回收机制相关知识点整理",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"PHP的垃圾回收机制相关知识点整理"吧!

PHP目前的开发框架,除了主流常用的FPM框架,想必就是基于swoole拓展的常驻内存开发了。

我们在FPM的开发模式中,每一次脚本程序结束之后,所有变量都会被销毁,内存会被释放,所以我们不用太担心。

但是常驻内存开发模式就不一样了,如果不注意变量内存的使用,无法很好的管理内存问题,会造成内存泄露。

所以,我们一定要熟悉PHP的垃圾回收机制(Garbage Collector 简称GC)

写时复制与引用计数

写时复制

在PHP7+版本中,有关于变量内存的操作特性,采用了写时复制,也就是说, 在必要的时候才会进行深拷贝(即发生写的时候才会进行深拷贝).

当变量值为interned string字符串型(变量名,函数名,静态字符串,类名等)时,变量值存储在静态区,内存回收被系统全局接管,引用计数将一直为1 。

当赋值变量的值为 整型,浮点型 时,php7底层将会直接把值存储(php7的结构体将会直接存储简单数据类型),refcount将为0,我们用代码来看一下:

$a = 'chris'.time();$b = $a;  //此时$b指向$a的同一个内存地址$c = $a;  //一样xdebug_debug_zval('a');//a:(refcount=3, is_ref=0)string 'chris1614780053' (length=15)我们通过Xdebug来观察变量的信息,他们指的都是同一个内存地址,是引用。
$a = 'chris'.time();$b = '青玄';$c = $a;xdebug_debug_zval('a');xdebug_debug_zval('b');//a:(refcount=2, is_ref=0)string 'chris1614780283' (length=15) //b:(interned, is_ref=0)string '青玄' (length=6) //存在了静态区我们通过Xdebug来观察变量的信息,这时$b的值已经发生了变化,这时候,才会使用新的内存空间,$a的引用次数-1。

引用计数

每个php变量存在一个叫"zval"的变量容器中。一个zval变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。第一个是"is_ref",是个bool值,用来标识这个变量是否是属于引用集合(reference set)。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。第二个额外字节是"refcount",用以表示指向这个zval变量容器的变量(也称符号即symbol)个数。

官方文档的描述

简单来说,就是给变量引用的次数进行计算,当计数refcount不等于0时,说明这个变量已经被引用,不能直接被回收,否则可以直接回收,用代码来看看把

$a='chris'.time();$b=$a;$c=$a; $b='青玄';unset($c);xdebug_debug_zval('a');//a:(refcount=1, is_ref=0)string 'chris1614780526'(length=5)//我们可以看到,删除$c,并不能把$a删除,因为refcount=1

内存泄漏

function a(){class A {   public $ref;   public $name;   public function __construct($name) { $this->name = $name; echo($this->name.'->__construct();'.PHP_EOL);   }   public function __destruct() {  echo($this->name.'->__destruct();'.PHP_EOL);   }}$a1 = new A('$a1');$a2 = new A('$a2');$a3 = new A('$3');$a1->ref = $a2;$a2->ref = $a1;unset($a1);unset($a2);echo('exit(1);'.PHP_EOL);}a();echo('exit(2);'.PHP_EOL);

当$a1和$a2的属性互相引用时,unset($a1,$a2) 只能删除变量的引用,却没有真正的删除类的变量,这是为什么呢?

首先,类的实例化变量分为2个步骤

1:开辟类存储空间,用于存储类数据

2:实例化一个变量,类型为class,值指向类存储空间

当给变量赋值成功后,类的引用计数为1,同时,a1->ref指向了a2,导致a2类引用计数增加1,同时a1类被a2->ref引用,a1引用计数增加1

当unset时,只会删除类的变量引用,也就是-1,但是该类其实还存在了一次引用(类的互相引用),

这将造成这2个类内存永远无法释放,直到被gc机制循环查找回收,或脚本终止回收(域结束无法回收).

PHP作用域的生命周期和变量回收

每个方法/函数都作为一个作用域,当运行完该作用域时,将会回收作用域内的所有变量,全局变量只有在脚本结束后才会回收。

我们可以通过以下方式来手动回收:

  • unset() : unset的回收原理其实就是引用计数-1,当引用计数-1之后为0时,将会直接回收该变量,否则不做操作(这就是上面内存泄漏的原因,引用计数-1并没有等于0)。

  • 赋值为null :=null和unset($a),作用其实都为一致,null将变量值赋值为null,原先的变量值引用计数-1,而unset是将变量名从php底层变量表中清理,并将变量值引用计数-1,唯一的区别在于,=null,变量名还存在,而unset之后,该变量就没了。

  • 变量覆盖回收:通过给变量赋值其他值(例如null)进行回收,但是从程序的内存占用来说,覆盖变量并不是意义上的内存回收,只是将变量的内存修改为了其他值.内存不会直接清空。

  • gc_collect_cycles :强制执行周期回收,在PHP执行中,一旦根缓冲区满了或者调用gc_collect_cycles() 函数时,就会执行垃圾回收

另外:为避免不得不检查所有引用计数可能减少的垃圾周期,PHP会有算法把疑似垃圾的变量,放在根缓冲区(root buffer)中,在根缓冲区满了的时候,也会对垃圾缓冲区进行一次回收。

到此,相信大家对"PHP的垃圾回收机制相关知识点整理"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

变量 内存 垃圾 机制 存储 作用 量值 容器 就是 指向 缓冲区 开发 缓冲 知识 知识点 信息 函数 周期 字节 时候 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海挚品互联网科技有限公司 山东特亿宝互联网科技有限公司 科技互联网项目 智能科技公司是互联网公司吗 金融科技创新监管互联网金融 新浪科技互联网 互联网高科技企业 玖二柒互联网科技公司待遇 新华互联网科技2019 科技与互联网哪个更好 呼和浩特新华互联网科技学院 互联网科技大奖都有哪些公司 互联网科技和信息 无锡工业互联网科技有限公司 上海京穆互联网科技有限公司 中国互联网有什么科技 郑州欣桑互联网科技有限公司 北京互联网科技类企业分布 青岛易易互联网科技 瑞安市蟠桃会互联网科技有限公司 中关村互联网 科技集团 互联网科技公司税收优惠 互联网 科技创业 常德市电业局互联网科技部 链环科技传统企业怎么转型互联网 翼展科技 首家互联网医院 科技赋能视角下互联网保险发展 互联网科技融合创新 瑞安市蟠桃会互联网科技有限公司 前海云享互联网科技
0