JVM内存管理
JVM内存数据区域分布如下图:
各个区域存放的数据类型如下图:
1、线程私有区域
程序计数器PC:相当于一个执行代码的指示器,用来确认下一行执行的代码的地址;每个线程都有一个程序计数器;该区域不会发生OOM。
虚拟机栈:我们平时说的栈就是这块区域,java虚拟机规范中定义了outofmemory和stackoverflow异常。
本地方法栈:native方法,java虚拟机规范中也定义了outofmemory和stackoverflow异常。
在hotspotVM中把虚拟机栈和本地方法栈合为了一个栈区。
2、共享数据区
方法区:包含了ClassLoader加载类信息,常量,静态变量,编译后的代码等数据,会发生OOM的错误;同时还包含了运行时常量池,运行时常量池存有字面量public satic final java常量以及符号引用 类,接口全名,方法名等。
java堆:虚拟机能管理的最大的一块内存,是 GC的主战场;存放的是对象的实例、数组的内容,会发生OOM。
GC如何确定垃圾回收
1、引用计数法
Object o1=new Object(); 计数+1=1 Object o2; o2=o1; 计数+1=2 o1=null; 计数为1 o1和o2都不会回收
如IOS6中的手动计数mrc与自动计数arc及cocos2dx采用的是引用计数法
缺点:互相引用容易出现计算器永不为0
2、可达性分析算法
可作为GC ROOT的对象:
(1)虚拟机栈正在运行使用的引用
(2)静态属性、常量
(3)JNI引用的对象
GC是需要2次扫描才回收对象,所以我们可以用finalize去救活丢失引用的对象,例如:
static App a; @Override protected void() throws Throwable{ super.finalize(); a=this; }
Android内存优化时,可根据可达性分析算法找到内存泄漏的根源。
3、回收也和引用类型有关系
强引用:Object obj=new Object();
软引用SoftReference:内存不足时回收,存放一些重要性不是很强又不能随便让清除的对象,比如图片切换到后台不需要马上显示了。
弱引用WeakReference:第一次扫到了,就标记下来,第二次扫到直接回收。
虚引用PhantomReference:幽灵、幻影引用 ,不对生存造成任何影响,用于跟踪GC的回收通知