对于总结PHP内存释放以及垃圾回收感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解总结php内存释放以及垃圾回收过程,并且为您提供关于c#的析构以及垃圾回收2、3事!、C#的析构以及垃圾回收
对于总结PHP内存释放以及垃圾回收感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解总结php内存释放以及垃圾回收过程,并且为您提供关于c# 的析构以及垃圾回收2、3事!、C# 的析构以及垃圾回收实例分析、flash垃圾回收机制,内存泄漏的常见情况及内存释放优化的原则、Java 内存分配及垃圾回收机制初探的宝贵知识。
本文目录一览:- 总结PHP内存释放以及垃圾回收(总结php内存释放以及垃圾回收过程)
- c# 的析构以及垃圾回收2、3事!
- C# 的析构以及垃圾回收实例分析
- flash垃圾回收机制,内存泄漏的常见情况及内存释放优化的原则
- Java 内存分配及垃圾回收机制初探
总结PHP内存释放以及垃圾回收(总结php内存释放以及垃圾回收过程)
引用赋值
上述代码中,我将一个字符串赋值给变量a,然后将a的引用赋值给了变量b。显然,这个时候的内存指向应该是这样的:
a和b指向了同一块内存区域,我们通过 var_dump($a,$b) 得到 string(5) "apple" string(5) "apple" ,这是我们预期的结果。
unset 函数
假如我想将 'apple' 这个字符串从内存中释放掉。我是这么做的:
但是通过再次打印 $a $b 两变量的信息,我得到了这样的结果:Notice: Undefined variable: a 和 string(5) "apple" 。奇怪,$a $b 同时指向一块内存区域,又明明将$a释放了,为什么$b还是'apple'。
其实是这样的,unset()这是将一个变量指针销毁了,并没有释放掉那块内存区域中存放的字符串,所以执行完操作之后,内存指向只是变成了这样:
要牢记重点: unset()并没有释放变量所指向的那块内存,而只是将变量指针销毁了。同时,将那块内存的 引用计数 减1,当引用计数为0时,也就是说当那块内存不被任何变量引用时,便会触发PHP的垃圾回收。
直接回收
那要怎样做才能真正释放掉 'apple' 所占用的内存呢?
利用上述方法,我们可以在 unset($a) 之后再 unset($b) ,将内存区域的所有引用都销毁,引用计数减为0了,自然就被PHP回收了。
当然,还有更直接的方法:
直接赋值 null 会将将 $a 所指向的内存区域置空,并将引用计数归零,内存便被释放。
脚本执行结束
PHP是脚本语言,当脚本执行结束之后,脚本内使用的所有内存都会被释放。
c# 的析构以及垃圾回收2、3事!
看书时,自己写的例子代码,了解到几个知识点,记载下来。同时发现自己手写代码的能力比较弱,还是得多写一下。
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
fun();
GC.Collect(); //4、若不显式回收,则控制台不打印回收行。
Console.WriteLine("end!");
}
public static void fun(){ //1、此处必须有static
A a=new A();
a.Dispose();
//GC.Collect(); //3、此处回收无效,因为a还没释放
}
public class A:IDisposable{
/* protected override void Finalize(){ //2、析构实际是重载Finalize,但不能直接写重载。编译器自动重写Finalize,所以代码中,只能用 析构函数。
Console.WriteLine("some one disposed!");
}*/
~A(){
Console.WriteLine("some one Finalize!");
}
public void Dispose(){
Console.WriteLine("some one disposed!");
}
}
}
}
5、该代码的输出为:
Hello World!
some one disposed!
end!
some one Finalize!
这个回收像极了异步调用!
6、IDisposable接口的Dispose方法,目的是“不用户不再使用对象时,要手工调用它”
比如文件打开,数据库访问等。需要及时释放。
明显这个概念和垃圾回收是两个概念。释放后,该对象仍然存在,有待运行环境来回收,见最后一行。
C# 的析构以及垃圾回收实例分析
C# 的析构以及垃圾回收实例分析
看书时,自己写的例子代码,了解到几个知识点,记载下来。同时发现自己手写代码的能力比较弱,还是得多写一下。
using System; namespace ConsoleApplication { public class Program { public static void Main(string[] args) { Console.WriteLine("Hello World!"); fun(); GC.Collect(); //4、若不显式回收,则控制台不打印回收行。 Console.WriteLine("end!"); } public static void fun(){ //1、此处必须有static A a=new A(); a.dispose(); //GC.Collect(); //3、此处回收无效,因为a还没释放 } public class A:Idisposable{ /* protected override void Finalize(){ //2、析构实际是重载Finalize,但不能直接写重载。编译器自动重写Finalize,所以代码中,只能用 析构函数。 Console.WriteLine("some one disposed!"); }*/ ~A(){ Console.WriteLine("some one Finalize!"); } public void dispose(){ Console.WriteLine("some one disposed!"); } } } }
1、该代码的输出为:
Hello World! some one disposed! end! some one Finalize!
这个回收像极了异步调用!
2、Idisposable接口的dispose方法,目的是“不用户不再使用对象时,要手工调用它”
比如文件打开,数据库访问等。需要及时释放。
明显这个概念和垃圾回收是两个概念。释放后,该对象仍然存在,有待运行环境来回收,见最后一行。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
flash垃圾回收机制,内存泄漏的常见情况及内存释放优化的原则
一、Flash Player垃圾回收机制:
Flash Player垃圾回收工作是由垃圾回收器(garbage collector)完成的。垃圾回收器是运行在后台的一个进程,它释放那些不再被应用所使用对象所占用的内存。不再被应用所使用的对象是指那些不再会被那些活动着(工作着)的对象所“引用”的对象。在AS中,对于非基本类型(Boolean,String,Number,uint,int)的对象,在对象之间传递的都是对象引用,而不是对象本身。删除一个变量只是删除了对象的引用,而不是删除对象本身。一个对象可以被多处引用,通过这些不同的引用所操作的都是同一个对象。
通过以下两段代码可以了解基本类型和非基本类型对象的差异:
基本类型的值传递:
private function testPrimitiveTypes():void
{
var s1:String="abcd"; //创建了一个新字符串s1,值为"abcd"
var s2:String=s1; //String是基本类型,所以创建了一个新的字符串s2,s2的值拷贝自s1。
s2+="efg"; //改变s2的值s1不会受影响。
trace("s1:",s1); //输出abcd
trace("s2:",s2); //输出abcdefg
var n1:Number=100; //创建一个新的number,值为100。
var n2:Number=n1; //Number是基本类型,所以又创建一个新number n2,n2的值拷贝自n1。
n2=n2+100; //改变n2对n1不会有任何影响。
trace("n1",n1); //输出100
trace("n2",n2); //输出200
}
非基本类型对象的引用传递:
private function testNonPrimitiveType():void
{
// 创建一个新对象,然后将其引用给变量a:
var a:Object = {foo:"bar"}
//将上面所创建对象的引用拷贝给变量b(通过变量b建立对对象的引用):
var b:Object = a;
//删除变量a中对对象的引用:
delete(a);
// 测试发现对象仍然存在并且被变量b所引用:
trace(b.foo); // 输出"bar",所以对象仍然存在
}
对于非基本类型对象,AS3采用两种方法来判定一个对象是否还有活动的引用,从而决定是否可以将其垃圾回收。一种方法是引用计数法,一种方法是标记清除法。
Reference Counting
引用计数法是判定对象是否有活动引用的最简单的一种方法,并且从AS1就开始在Flash中使用。当创建一个对对象的引用后,对象的引用计数就加一,当删除一个引用时,对象的引用技术就减一。如果对象的引用计数为0,那么它被标记为可被GC(垃圾回收器)
删除。例如:
var a:Object = {foo:"bar"}
// 现在对象的引用计数为1(a)
var b:Object = a;
// 现在对象的引用计数为2(a和b)
delete(a);
// 对象的引用计数又回到了1 (b)
delete(b);
// 对象的引用计数变成0,现在,这个对象可以被GC释放内存。
引用计数法很简单,并且不会增加cpu开销,可惜的是,当出现对象之间循环引用时它就不起作用了。所谓循环引用就是指对象之间直接或者间接地彼此引用,尽管应用已经不再使用这些对象,但是它们的引用计数仍然大于0,因此,这些对象就不会被从内存中移除。请看下面的范例:
创建第一个对象:
var a:Object = {};
// 创建第二个对象来引用第一个对象:
var b:Object = {foo:a};
//使第一个对象也引用第二个对象:
a.foo = b;
// 删除两个活动引用:
delete(a);
delete(b);
上面的例子中两个活动引用都已被删除,因此在应用程序中再也无法访问这两个对象。但是它们的引用计数都是1,因为它们彼此相互引用。这种对象间的相互引用可能会更加复杂(a引用b,b引用c,c又引用a,诸如此类),并且难以在代码中通过删除引用来使得引用技术为变为0。Flash player 6 和7中就因为XML对象中的循环引用而痛苦,每个XML节点既引用了该节点的子节点,又引用了该节点父节点。因此,这些XML对象永远不会释放内存。好在 player 8增加了一种新的GC技术,叫做标记清除。
标记清除(Mark Sweeping)
AS3使用的第二种查找不活动对象的GC策略就是标记清除。 Player从应用的根节点开始(在AS3中通常被称为”根(root)”),遍历所有其上的引用,标记每个它所发现的
对象。然后迭代遍历每个被标记的对象,标记它们的子对象。这个过程第归进行,直到Player遍历了应用的整个对象树并标记了它所发现的每个东西。在这个过程技术的时候,可以安全地认为,内存中那些没有被打标记的对象没有任何活动引用,因此可以被安全地释放内存。可以通过下图可以很直观地了解这种机制(绿色的引用在标记清除过程中被遍历,绿色对象被打上了标记,白色对象将被释放内存)
标记清除机制非常准确,但是这种方法需要遍历整个对象结构,因此会增大cpu占用率。因此,Flash Player9为了减少这种开销只是在需要的时候偶尔执行标记清除活动。
注意:上面所说的引用指的是“强引用(strong reference)”,flash player在标记清除过程中会忽略“弱引用(weakness reference )”,也就是说,弱引用在标记清除过程中不被当做引用,不会阻止垃圾回收。
垃圾回收的时机
Flash Player在运行时请求内存的速度受限于浏览器。因此,Flash Player采用小量请求大块内存,而不是大量请求小块内存的内存请求策略。同样,Flash Player在运行时释放内存速度也相对较慢,所以Flash Player会减少释放内存的次数,只有在必要的时候才释放内存。也就是说,Flash Player的垃圾回收只有在必要的时候才会执行。
当前,Flash Player的垃圾回收发生在Flash Player需要另外请求内存之前。这样,Flash Player可以重新利用垃圾对象所占用的内存资源,并且可以重新评估需要另外请求的内存数量,也会节省时间。
在程序的实际运行中验证了以上的说法,并不是每次应用申请内存时都会导致垃圾回收的执行,只有当Flash占用的内存紧张到一定程度时才会执行真正的垃圾回收,如果应用中内存开销增长是匀速的,那么计算机物理内存越大,则垃圾回收触发周期越长。在我的测试环境中,计算机有2G的物理内存,直到打开FLSH 应用的浏览器占用700M物理内存之后才会导致Flash Player回收垃圾内存。
二、开发中导致内存泄露的常见情况
通过上面的讨论我们可以知道,只要对象被其他活动对象(仍在运行的)所引用,那么这个对象就不会被垃圾回收,从而可能造成内存泄露。
在我们的开发中,如下的一些情形会导致内存泄露:
(一)被全局对象所引用的对象在它们不再使用时,开发者忘记从全局对象上清除对它们的引用就会产生内存泄露。常见的全局对象有stage,主 Application,类的静态成员以及采用singleton模式创建的实例等。如果使用第三方框架,比如:PureMvc,Cairongorm 等,要注意这些框架的实现原理,尤其要注意框架里面采用singleton模式创建的controler和Model。
(二) 无限次触发的Timer会导致内存泄漏。无论无限次触发的 Timer 是否为全局对象,无限次触发的Timer本身以及注册在Timer中的监听器对象都不会被垃圾回收。
(三)通过隐式方式建立的对象之间的引用关系更容易被程序员所忽略,从而导致内存泄露。最常见的以隐式方式建立对象之间的引用就是“绑定”和“为对象添加事件监听器”。通过测试我们发现“绑定”不会造成内存泄露,对象可以放心地绑定全局对象。而调用addEventListener()方法“为对象添加事件监听器”则可能产生内存泄露,大多数内存泄露都因此而来:下面代码:
a.addEventListener(Event.EVENT_TYPE,b.listenerFunction)
使得a对象引用了b对象,如果a对象是一个全局对象(全局对象在应用运行期间始终存在),则b对象永远不会被垃圾回收,可能会造成内存泄露。比如下面的代码就有造成内存泄露的可能:
this.stage.addEventListener(Event.RESIZE,onResize);
上面代码中的stage是UIComponent的stage属性,表示当前Flex应用运行的“舞台”。
不过,通过以下三种方式使用addEventListener方法不会造成内存泄露:
1.
用弱引用方式注册监听器。就是调用时将addEventListener的第五个参数置为true,例如:someObject.addEventListener(MouseClick.CLICK,otherObject.handlerFunction,false,true);
2.
自引用的方式。即:为对象添加的监听处理函数是对象本身的方法。例如:
this.addEventListener(MouseClick.CLICK,this. handlerFunction);
3子对象引用。即:为子对象添加的监听处理函数是父上对象的方法。例如:
private var childobject:UIComponent = new UIComponent; addChild(childobject); childobject.addEventListener(MouseEvent.CLICK,this.clickHandler);
三、内存释放优化原则
1. 被删除对象在外部的所有引用一定要被删除干净才能被系统当成垃圾回收处理掉;
2. 父对象内部的子对象被外部其他对象引用了,会导致此子对象不会被删除,子对象不会被删除又会导致了父对象不会被删除;
3. 如果一个对象中引用了外部对象,当自己被删除或者不需要使用此引用对象时,一定要记得把此对象的引用设置为 null;
4. 本对象删除不了的原因不一定是自己被引用了,也有可能是自己的孩子被外部引用了,孩子删不掉导致父亲也删不掉;
5. 除了引用需要删除外,系统组件或者全局工具、管理类如果提供了卸载方法的就一定要调用删除内部对象,否则有可能会造成内存泄露和性能损失;
6. 父对象立刻被删除了不代表子对象就会被删除或立刻被删除,可能会在后期被系统自动删除或第二次移除操作时被删除;
7. 如果父对象 remove 了子对象后没有清除对子对象的引用,子对象一样是不能被删除的,父对象也不能被删除;
8. 注册的事件如果没有被移除不影响自定义的强行回收机制,但有可能会影响正常的回收机制,所以最好是做到注册的事件监听器都要记得移除干净。
9. 父对象被删除了不代表其余子对象都删除了,找到一种状态的泄露代码不等于其他状态就没有泄露了,要各模块各状态逐个进行测试分析,直到测试任何状态下都能删除整个对象为止。
四、内存泄露举例
1. 引用泄露:对子对象的引用,外部对本对象或子对象的引用都需要置 null ;
2. 系统类泄露:使用了系统类而忘记做删除操作了,如 BindingUtils.bindSetter() , ChangeWatcher.watch() 函数 时候完毕后需要调用 ChangeWatcher.unwatch() 函数来清除引用,否则使用此函数的对象将不会被删除;
类似的还有 MUSIC , VIDEO , IMAGE , TIMER , EVENT , BINDING 等。
3. 效果 泄露:当对组件应用效果 Effect 的时候,当本对象本删除时需要把本对象和子对象上的 Effect 动画停止掉,然后把 Effect 的 target 对象置 null; 如果不停止掉动画直接把 Effect 置 null 将不能正常移除对象。
4. SWF 泄露:要完全删除一个 SWF 要调用它的 unload() 方法并且把对象置 null;
5. 图片泄露:当 Image 对象使用完毕后要把 source 置 null;( 为测试 ) ;
6. 声音、视频 泄露 : 当不需要一个音乐或视频是需要停止音乐,删除对象,引用置 null;
五、内存泄露解决方法
1. 在组件的 REMOVED_FROM_STAGE 事件回掉中做垃圾处理操作(移除所有对外引用(不管是 VO 还是组件的都需要删除),删除监听器,调用系统类的清除方法)
先 remove 再置 null,确保被 remove 或者 removeAll 后的对象在外部的引用全部释放干净 ;
2. 利用 Flex 的性能优化工具 Profile 来对项目进程进行监控,可知道历史创建过哪些对象,目前有哪些对象没有被删除,创建的数量,占用的内存比例和用量,创建过程等信息 ;
Java 内存分配及垃圾回收机制初探
一、运行时内存分配
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。
这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。
线程私有区域(生命周期与线程相同)
a) 虚拟机栈
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame[1])用于存储局部变量表、 操作数栈、 动态链接、 方法出口等信息。 每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
虚拟机栈中有一个局部变量表,存放了编译期可知的各种基本数据类型(boolean、 byte、 char、 short、 int、float、 long、 double)、 对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
b)本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。
c) 程序计数器
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。 因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
共享数据区
a)堆
对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。 在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。
b)方法区
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚
拟机加载的类信息、 常量、 静态变量、 即时编译器编译后的代码等数据。
相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。 这区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说,这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是必要的。
Java对象创建过程
a) 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、 解析和初始化过。 如果没有,那必须先执行相应的类加载过程。
b) 为对象分配内存(对象所需内存大小在类加载完成后便完全确定),对象所需内存的大小在类加载完成后便可完全确定(如何确定将在2.3.2节中介绍),为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。
二、垃圾对象判定
1. 引用计数法
每个对象都有一个引用计数的属性,用来保存该对象被引用的次数。当引用次数为0时,就意味着该对象没有被引用了,也就不会在使用这个对象了,可以判定为垃圾对象。但是,这种方式有一个很大的Bug,就是无法解决对象间相互引用或者循环引用的问题:当两个对象相互引用,他们两个和其他任何对象也没有引用关系,它俩的引用次数都不为0,因此不会被回收,但实际上这两个对象已经不再有用了。
2. 可达性分析(根搜索法)
在主流的商用程序语言(Java、 C#,甚至包括前面提到的古老的Lisp)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。 如图3-1所示,对象object 5、 object 6、 object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。
这里的GC Roots对象包括以下几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)引用的对象。
注: 这里涉及Java中到四种引用,不再细说。
在此我向大家推荐一个架构学习交流群。交流学习群号:478030634 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
三、典型的垃圾收集算法
在确定了哪些垃圾可以被回收后,垃圾收集器要做的事情就是开始进行垃圾回收,但是这里面涉及到一个问题是:如何高效地进行垃圾回收。由于Java虚拟机规范并没有对如何实现垃圾收集器做出明确的规定,因此各个厂商的虚拟机可以采用不同的方式来实现垃圾收集器,所以在此只讨论几种常见的垃圾收集算法的核心思想。
1.Mark-Sweep(标记-清除)算法
这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。具体过程如下图所示:
从图中可以很容易看出标记-清除算法实现起来比较容易,但是有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。
2.Copying(复制)算法
为了解决Mark-Sweep算法的缺陷,Copying算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。具体过程如下图所示:
这种算法虽然实现简单,运行高效且不容易产生内存碎片,但是却对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。
很显然,Copying算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么Copying算法的效率将会大大降低。
3.Mark-Compact(标记-整理)算法
为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。具体过程如下图所示:
4.Generational Collection(分代收集)算法
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。
而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。
注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。
大家觉得文章对你还是有一点点帮助的,大家可以点击下方二维码进行关注。 《Java烂猪皮》 公众号聊的不仅仅是Java技术知识,还有面试等干货,后期还有大量架构干货。大家一起关注吧!关注烂猪皮,你会了解的更多..............
今天关于总结PHP内存释放以及垃圾回收和总结php内存释放以及垃圾回收过程的介绍到此结束,谢谢您的阅读,有关c# 的析构以及垃圾回收2、3事!、C# 的析构以及垃圾回收实例分析、flash垃圾回收机制,内存泄漏的常见情况及内存释放优化的原则、Java 内存分配及垃圾回收机制初探等更多相关知识的信息可以在本站进行查询。
本文标签: