Android内存泄漏、内存分配的几种策略
先给大家讲一个今天看到的一个笑话:
有一人彩票中奖中了500W,记者专门对他进行了采访;
记者:“请问你中奖之后有什么打算吗?”
“先买一套房子吧”;
记者:“然后呢?”
“然后剩下的慢慢还”。
看了之后也是醉了,也不吐槽现在各地的房价了,现在在帝都工作,这个城市搞不懂,还是好好哦的敲代码吧,昨天看到了一些东西,与之前自己理解的有一些不一样的地方,所以在这里总结下,如果能帮到你,表示非常荣幸,要是有什么不对的或者让你误解的,先表示歉意。
内存泄漏
概念:当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而就导致对象不能被回收。这种导致了本该被回收的对象不能被回收而停留在堆内存中,就产生了内存泄漏
内存泄漏会造成我们仅限的内存空间可使用的内存越来越少,会造成应用程序的卡顿甚至崩溃,想知道每款手机为每个app进程分配的内存可以在AS里的Android Monitor里面的Memory中看到每个app系统分配的内存空间,当然利用Android Monitor也可以进行监视内存变化,分析内存泄漏,这些以后再说。首先我来给大家分析下内存泄漏发生的一二三。
JVM内存分配的策略有:
1、静态区
静态区和我之前的理解是一样的,内存在程序编译的时候就已经分配好,这块的内存在程序整个运行期间都一直存在。它主要存放静态数据、全局的static数据和一些常量。
2、栈区
栈区和我之前的理解不太一样,先说下我之前错误的理解,之前我一直以为在程序运行期间所有的基础类型变量都是在栈区里面,所有的对象引用都在站里面,不过昨天我才知道自己的理解太过片面,其实栈区中存储的数据是函数(方法)在执行时,函数一些内部变量的存储放在栈上面创建,函数执行结束的时候这些存储单元就会自动被释放掉。当然提前说一下,在方法内部实例化的对象 即:通过new关键字创建的对象是保存在堆中,对象的引用是在栈里面。等下面描述完了堆一块给大家举个例子。
3、堆区
堆是不连续的内存区域,堆空间比较灵活也特别大。栈是一块连续的内存区域,大小是有操作系统觉决定的,我们所说的内存泄漏都是发生在堆里,因为栈里的数据在函数执行完成之后已经进行了销毁,所以堆是出现内存泄漏的地方,堆里面存放的数据就是我们new出来的东西了。
举个例子:
public class Main
{
int a=1; //之前一直认为是在栈里,结果想错了,因为a属于Main,所以呀在实例化的Main对象肯定在堆里
Student s=newStudent();//引用在栈里,对象在堆里
public void XXX()
{
intb =1;//栈里面,因为是是方法内部变量
Student s2 =newStudent(); //引用在栈里,对象在堆里
}
}
在上面的这个类里面,如果我们Main main = new Main();执行了这句代码之后,在内存中main对象放在堆中,main引用是在栈中,因为a这个变量是属于main的,所以a也是在堆中,但是如果main.XXX()调用了该方法,那么b肯定在站里面,s2的引用在栈里, 对象在堆里。
总结一下:
1.成员变量全部存储在堆中(包括基本数据类型,引用的对象实体)---因为他们属于类,类对象最终还是要被new出来的。
2.局部变量的基本数据类型和引用存储于栈当中,引用的对象实体存储在堆中。-----因为他们属于方法当中的变量,生命周期会随着方法一起结束。