由于Android应用的沙箱机制,每个应用所分配的内存大小是有限度的,因此内存会显得非常珍贵,如果我们的内存占用超过了一定的水平就会出现OutOfMemory错误
目录
内存概述
RAM(random access memory)随机存取存储器.(通俗的说就是内存)
1.Java的内存分配策略:
Java内存分配时会涉及到以下区域:
栈(Stack):一些基本类型的变量和对象的引用都是在栈内存中分配,当超过变量的作用域后,java会自动释放该变量分配的内存(对象本身不存放在栈中,而是存放在堆中)
堆(Heap): 通常用来存放new出来的对象和数组,由java垃圾回收器回收.
静态存储区(static field): 编译时就分配好,在程序整个运行期间都存在.它主要存放静态数据和常量
还一个CPU存储区:
寄存器(Registers): 速度最快的存储场所,因为寄存器位于处理器内部,我们在程序中无法控制
2.堆栈的特点:
栈:
定义一个变量时,Java在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放为该变量所分配的内存空间.
栈的存取速度比堆要快,仅次于寄存器.但是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性
栈中的数据可以共享,它是由编译器完成的,有利于节省空间
例如:需要定义两个变量int a = 3;int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有,就将3存放进来再将a指向3.
接着处理int b = 3,创建完b的引用变量后在栈中已经有3这个值,便将b直接指向3.这样,就出现了a与b同时均指向3的情况.
这时,如果再让a=4,那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并让a指向4.
如果已经有了,则直接将a指向这个地址.因此a值的改变不会影响到b的值。
堆:
当堆中通过new产生数组和对象超出其作用域后,它们不会被释放,只有在没有引用变量指向它们的时候才变成垃圾,不能再被使用,并且只有等被垃圾回收器回收才回释放内存.这也是Java比较占内存的原因.
堆是一个运行时数据区,可以动态地分配内存大小,因此存取速度较慢.
如上例子,栈中a的修改并不会影响到b,而在堆中一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量
- APP内存占用信息查询
float max = Runtime.getRuntime().maxMemory() * 1.0f / (1024 * 1024);
float total = Runtime.getRuntime().totalMemory() * 1.0f / (1024 * 1024);
float free = Runtime.getRuntime().freeMemory() * 1.0f / (1024 * 1024);
查看系统设置单个进程的内存上限
C:\Users\Administrator>adb shell
sagit:/ $ getprop|grep heapgrowthlimit
[dalvik.vm.heapgrowthlimit]: [256m]
3.java中四种引用类型:
强引用(StrongRe