说起内存我们要先了解JAVA虚拟机
JAVA虚拟机
java虚拟机在运行程序时会在内存空间分配一块区域用于程序的运行,虚拟机又会把这一块区域划分为若干个不同的数据块
线程私有:程序计数器、虚拟机栈、本地方法栈;
共享数据区:方法区、java堆。
程序计数器相当于一个执行代码的指示器,用来确认下一行执行代码的地址,每个线程都有一个,没有OOM的区。
虚拟机栈:我们平常所说的栈就是指这一块区域,虚拟机规范中定义了OOM和stackoverflow异常。
本地方法栈:java虚拟机规范中定义了OOM和stackoverflow异常。
在hotspotVM(Sun JDK虚拟机)把虚拟机栈和本地方法栈合为一个栈区。
方法区:分配给ClassLoader加载类信息,常量,静态变量,编译后的代码。
堆区:分配给对象实例和数组,是虚拟机管理的最大的一块内存,是GC的主战场。
GC垃圾回收器
GC如何确定内存回收:
1、引用计数算法
就是对象在引用一次计数+1,置空时-1,只有计数为0时进行回收,其缺点也很明显,就是互相引用时计数永不为0。
2、可达性分析算法
当一个对象到GC Root没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。
3、引用类型
强引用:不会主动被回收。
软引用(SoftReference):内存不足时回收,存放一些重要性不是很强又不能随便让清除的对象,比如图片切换到后台不需要马上显示了。
弱引用(WeakReference):第一次扫到了,就标记下来,第二次扫到直接回收。
虚引用(PhantomReference):幽灵幻影引用 不对生存造成任何影响,用于跟踪GC的回收通知
内存泄漏
产生原因:一个长生命周期的对象持有一个短生命周期对象的引用,通俗讲就是该回收的对象,因为引用问题没有被回收,最终会产生OOM。