前言

GC的全称是Garbage Collection也就是垃圾回收的意思,在PHP中,是使用引用计数和回收周期来自动管理内存对象的,当一个对象被设置为NULL,或者没有任何指针指向时,他就会变成垃圾,被GC机制回收掉。

环境配置

php.ini终配置好xdebug,xdebug_debug_zval是用来查看容器变量内容的函数

<?php
$a = "F12";
xdebug_debug_zval("a");
?>



在PHP GC机制中,当程序终止时就会让变量的refcount减1,如果refcount-1为0的话,就会销毁回收该变量

引用计数

is_ref表示该变量是否被引用,操作系统学的好的同学应该很容易理解该内容

<?php
$a = "F12";
$b = &$a;
xdebug_debug_zval("a");
?> # 运行结果
a: (refcount=2, is_ref=1)='F12'

$b是$a的引用,所以is_ref=1,同时refcount也会加1,因为此时是有两个变量的(两变量指向同一个地址),所以销毁时要让refcount减2。

当变量是array类型时,也是一样的规则

<?php
$a = "F12";
$arr = array(0=>"test", 1=>&$a);
xdebug_debug_zval("arr");
?>
# 运行结果
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=2, is_ref=1)='F12')

如果我们在引用前将$a销毁会发生什么?

<?php
$a = "F12";
unset($a);
$arr = array(0=>"test", 1=>&$a);
xdebug_debug_zval("a");
xdebug_debug_zval("arr");
?>
# 运行结果
a: (refcount=2, is_ref=1)=NULL
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=2, is_ref=1)=NULL)
<?php
$a = "F12";
$arr = array(0=>"test", 1=>&$a);
unset($a);
xdebug_debug_zval("a");
xdebug_debug_zval("arr");
?>
# 运行结果
a: no such symbol
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=1, is_ref=1)='F12')

第一种情况,$a没有被销毁,因为在之后又引用了$a,所以$a只是指向了一个NULL,第二种情况就把$a销毁了

PHP GC在反序列化中的使用

一个简单的demo

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
echo "construct(".$num.")"."\n";
}
public function __destruct()
{
echo "destruct(".$this->num.")"."\n";
}
}
$a=new gc(1);
$b=new gc(2);
$c=new gc(3); # 运行结果
construct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)
destruct(1)

先创建的对象最后销毁,看看变量的内容情况:



可以看到refcount为1,所以当程序结束时,减1就会被回收

如果我们不把new的gc对象赋值给$a会怎样?

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
echo "construct(".$num.")"."\n";
}
public function __destruct()
{
echo "destruct(".$this->num.")"."\n";
}
}
new gc(1);
$b=new gc(2);
$c=new gc(3); # 运行结果
construct(1)
destruct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)

可以看到第一个gc对象,创建完就被回收了,因为没被其它变量引用,它的refcount一开始就是0,所以直接被回收

绕过Exception异常

思路一

一个简单的demo:

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = new gc(1);
$ser = serialize($a);
$b = unserialize($ser);
throw new Exception("F12 is bad");

正常来说会输出一个Hello World!,但是因为触发了异常,所以对象并没有被回收



我们修改一下代码:

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = array(0=>new gc(1),1=>1);
$ser = serialize($a);
echo $ser;
$ser = 'a:2:{i:0;O:2:"gc":1:{s:3:"num";i:1;}i:0;i:1;}';
$b = unserialize($ser);
throw new Exception("F12 is bad");

这里我们我们修改序列化的内容,将$a[0]随便指向谁,从而使new的gc对象没有引用的变量,所以触发提前回收,跟上面举的直接new gc,并不赋值是一个道理

思路二

这种方法更加简单粗暴,我们只需要让序列化的数据出错,那么当反序列化时出错时,也会让该对象提前回收

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = new gc(1);
$ser = serialize($a);
echo $ser;
$ser = 'O:2:"gc":1:{s:3:"num";i:1;';
$b = unserialize($ser);
throw new Exception("F12 is bad");

这里我们删去一个},依然输出了Hello World!

PHP GC回收机制详解的更多相关文章

  1. 转 Java虚拟机5:Java垃圾回收(GC)机制详解

    转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...

  2. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

  3. GC垃圾回收机制详解

    JVM堆相关知识    为什么先说JVM堆?  JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方式就是那些new一类的操作 ...

  4. JVM的垃圾回收机制详解和调优

    JVM的垃圾回收机制详解和调优 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都 ...

  5. PHP的垃圾回收机制详解

    原文:PHP的垃圾回收机制详解 最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制.本文参考了PHP手册. 在理解PHP垃圾回收机制(GC)之前,先了解一 ...

  6. JVM架构和GC垃圾回收机制详解

    JVM架构图分析 下图:参考网络+书籍,如有侵权请见谅 (想了解Hadoop内存溢出请看:Hadoop内存溢出(OOM)分类.参数调优化) JVM被分为三个主要的子系统 (1)类加载器子系统(2)运行 ...

  7. Java虚拟机5:Java垃圾回收(GC)机制详解

    哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径使用的对象.那么如何找到这些对象? 1.引用计数法 这个算法的实现是,给对象中添 ...

  8. Java垃圾回收(GC)机制详解

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

  9. Java垃圾回收【GC】机制详解

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

  10. Python垃圾回收机制详解

    一.垃圾回收机制 Python中的垃圾回收是以引用计数为主,分代收集为辅.引用计数的缺陷是循环引用的问题. 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存. #e ...

随机推荐

  1. 云图说丨带你了解GaussDB(for Redis)双活解决方案

    摘要:GaussDB(for Redis)推出了双活解决方案,基于GaussDB NoSQL统一架构,通过两个数据库实例之间的数据同步,达成数据的一致性. 本文分享自华为云社区<[云图说]一张图 ...

  2. 【火热招募】一文看懂华为云IoT Edge边缘计算开发者大赛技术亮点

    摘要:第二届边缘计算开发者大赛已启动,赛程时间将从9月持续到12月,华为云IoT Edge · 边云协同赛道奖金池高达40万元. 近日,第二届边缘计算开发者大赛已启动(查看启动仪式),全球揭榜挂帅火热 ...

  3. 华为云开源的Karmada正式成为CNCF首个多云容器编排项目

    摘要:CNCF(云原生计算基金会)正式接纳由华为云贡献的多云容器编排项目Karmada,迎来CNCF首个多云容器编排项目. 北京时间9月15日,CNCF(云原生计算基金会)正式接纳由华为云贡献的多云容 ...

  4. iOS 应用上架的步骤和工具简介

    编辑 APP开发助手是一款能够辅助iOS APP上架到App Store的工具,它解决了iOS APP上架流程繁琐且耗时的问题,帮助跨平台APP开发者顺利将应用上架到苹果应用商店.最重要的是,即使没有 ...

  5. IAST 初探:博采众长、精准定位、DevOps友好

    之前的文章中,我们了解了 SAST 和 DAST,本文将介绍将两者优势相结合的安全测试技术--IAST. ✦ ✦ 交互式应用安全测试(IAST)是一个自动识别和诊断应用程序和 API 漏洞的技术,它结 ...

  6. django基本流程

    创建项目 django-admin startproject web cd web python manage.py startapp weblist 生成迁移文件 python manage.py ...

  7. Flask小知识集合

    全局变量g的使用 flask在上下文中提供了四种变量,分别是: 变量名 上下文 说明 current_app 应用上下文 当前激活程序的程序实例 g 应用上下文 处理请求时用作临时存储的对象.每次请求 ...

  8. 《Flask Web 开发指南 pt.1》

    最近在看辉哥的<Flask Web 开发实战>,这才有了<Flask Web 开发指南>系列的文章,偏向学习笔记多一点,也有实战的内容 看下这个系列的文章我能写多少篇 :) 愚 ...

  9. Java | 个人学习指南笔记

    前言:由于作者已经有C语言,C++和Python语言的基础了,所以在文章的编写时会以这几门编程语言作对比.本文学习自 C语言中文网的 Java 教程,部分内容引用自这.引用内容仅作学习使用. 第1章: ...

  10. 基于阿里云Serverless函数计算开发的疫情数据统计推送机器人

    一.Serverless函数计算 什么是Serverless? 在<Serverless Architectures>中对 Serverless 是这样子定义的: Serverless w ...