内存泄漏—堆和栈

来源:互联网 发布:知秋的意思 编辑:程序博客网 时间:2024/06/06 19:48

内存泄漏——Java内存分配策略、栈和堆

生活就是如此,若不一步步走,永远看不到曙光——《你所谓的稳定不过是在浪费生命》

今天看到一篇好好的文章:Android面试被问到内存泄漏了杂整?
以下大部分内容摘取上面的链接,也有另外一小点自己查的资料!

Java内存分配策略:

Java程序运行的内存分配策略有三种:静态分配,栈式分配,和堆式分配。对应的三种策略使用的内存空间分别是静态存储区(也称为方法区),栈区,和堆区。

  • 静态存储区:主要存放静态数据,全局static数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。
  • 栈区:当方法执行时,方法内部的局部变量都简历在栈内存中,并在方法结束后自动四方分配的内存。因为栈内存分配是在处理器的指令集当中,所以效率很高,但是分配的内存容量有限。
  • 堆区:又称动态内存分配,通常就是指在程序运行时直接new出来的内存,这部分内存在不适用时将会有Java垃圾回收器来负责回收。

栈与堆的区别:

在方法体内定义的(局部变量)一些基本类型的变量和对象的引用变量都在方法的栈内存中分配。当在一段方法块中定义一个变量时,Java就会在栈中为其分配内存,当超出变量作用域时,该变量也就无效了,此时占用的内存就会释放,然后会被重新利用。

堆内存用来存放所有new出来的对象(包括该对象内的所有成员变量)和数组。在堆中分配的内存,由Java垃圾回收管理器来自动管理。在堆中创建一个对象或者数组,可以在栈中定义一个特殊的变量,这个变量的取值等于数组或对象在堆内存中的首地址,这个特殊的变量就是我们上面提到的引用变量。我们可以通过引用变量来访问堆内存中的对象或者数组。

举个例子:

public class Sample {int s1 = 0;Sample mSample1 = new Sample();public void method() {    int s2 = 0;    Sample mSample2 = new Sample();}}Sample mSample3 = new Sample();

如上局部变量s2mSample2存放在栈内存中,mSample3所指向的对象存放在堆内存中,包括该对象的成员变量s1mSample1也存放在堆中,而它自己则存放在栈中。

结论:

局部变量的基本类型和引用存储在栈内存中,引用的实体存储在堆中。——因它们存在于方法中,随方法的生命周期而结束。

成员变量全部存储于堆中(包括基本数据类型,引用和引用的对象实体)。——因为它们属于类,类对象终究要被new出来使用。

总结:栈的优势是,存取速度比堆要快

哪些数据存放在栈中?

答:基本数据类型(int、short、long、byte、float、double、boolean、char)的变量都存放于栈中。

哪些数据存放在堆中?

答:堆内存用于存放由new创建的对象和数组,即堆主要是用来存储对象的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。