文章目录
自动内存管理
java内存区域与内存溢出异常
运行时数据区域
Program Counter Register
Java Virtual Machine Stack
Native method Stack
Java 堆
Method area
直接内存
垃圾收集器和内存分配策略
那些对象需要回收?
引用计数法
可达性分析
引用分类
两次标记
回收方法区
什么时候回收?
如何回收?
heap的内存划分
1.标记-清除算法
标记:标记出所有要回收的对象
清除:回收被标记对象
缺点:效率低,这两个操作效率都不高
空间问题,形成大量不连续碎片空间。当以后需要分配较大的对象时,无法找到足够大的连续空间,触发gc。
2.标记-复制算法
内存分为相等的两块,需要回收时,把存活的对象拷贝到另一半,清除当前的整个块,以保证空间连续性。
缺点:代价高。
现在一般分为三块,Eden和两块较小的Survivor。当回收时,将存活对象放到另一个Survivor中,清除当前Survivor和Eden.
3.标记-整理算法
标记:标记所有要回收的对象。
整理:将存活对象向一段移动,然后直接清理到边界以外的内存空间
4.分代收集算法
分代:新生代,老生代
新生代:存活少,使标记-复制算法。
老生代:存活多,使用标记清除或标记整理算法。
代码如何产生不可达变量
非线程对象不被指向或超出作用域
线程对象线程未启动或停止
改变对象引用,置为null或指向其他对象。
Object x=new Object();//object1
Object y=new Object();//object2
x=y;//object1 变为垃圾
x=y=null;//object2 变为垃圾
超出作用域
if(i==0){
Object x=new Object();//object1
}//括号结束后object1将无法被引用,变为垃圾
类嵌套导致未完全释放
class A{
A a;
}
A x= new A();//分配一个空间
x.a= new A();//又分配了一个空间
x=null;//将会产生两个垃圾
线程中的垃圾
class A implements Runnable{
void run(){
//....
}
}
//main
A x=new A();//object1
x.start();
x=null;//等线程执行完后object1才被认定为垃圾