程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出进行出栈和入栈。
java堆和方法区不一样,只有程序运行期间才能知道创建了哪些对象,这些对象的分配和回收是动态的。
对象已死的判断方法:
1.引用计数器算法:给对象添加一个引用计数器,当引用时计数器加1 ,引用失效时减1
缺点:难以解决对象之间循环引用问题。
2.根搜索算法(java采用)
在根搜索算法中不可达的对象不一定必死,宣告一个对象死亡要经过两次标记:
1.第一次标记并进行执行finalize方法
2.如果在finalize方法成功拯救自己,第二次标记时将它移出“即将回收”的集合
来看下面一段代码:
java堆和方法区不一样,只有程序运行期间才能知道创建了哪些对象,这些对象的分配和回收是动态的。
对象已死的判断方法:
1.引用计数器算法:给对象添加一个引用计数器,当引用时计数器加1 ,引用失效时减1
缺点:难以解决对象之间循环引用问题。
2.根搜索算法(java采用)
在根搜索算法中不可达的对象不一定必死,宣告一个对象死亡要经过两次标记:
1.第一次标记并进行执行finalize方法
2.如果在finalize方法成功拯救自己,第二次标记时将它移出“即将回收”的集合
来看下面一段代码:
public class FinalizeGC {
public static FinalizeGC SAVE_HOOK=null;
public void isAlive(){
System.out.println("yes, i am still alive:");
}
@Override
protected void finalize() throws Throwable{
super.finalize();
System.out.println("finalize method executed!");
FinalizeGC.SAVE_HOOK=this;
}
public static void main(String[] args) throws InterruptedException
{
SAVE_HOOK=new FinalizeGC();
SAVE_HOOK=null;
System.gc();
Thread.sleep(500);//暂停500ms等待执行finalize方法
if(SAVE_HOOK!=null){
SAVE_HOOK.isAlive();
}else{
System.out.println("i am dead!");
}
//自救失败 ,代码和上面一样
//原因:任何一个对象的finalize方法都只会被系统调用一次,
//如果对象面临下一次回收,它的finalize方法不会被再次执行
SAVE_HOOK=null;
System.gc();
Thread.sleep(500);
if(SAVE_HOOK!=null){
SAVE_HOOK.isAlive();
}else{
System.out.println("i am dead!");
}
}
}