java 高手进 gc() 问题?
import java.util.Vector;
public class Test_heap
{
public static void main(String[] args) throws InterruptedException
{
new MyThread1().start();//执行用1s
//上面线程执行结束内存没有被回收 任务管理器显示占内存529mb
Thread.sleep(10*1000);
new MyThread2().start();
//上面线程执行结束时,任务管理器显示占内存仍然是529mb
Thread.sleep(10*1000);
new MyThread1().start();
//上面线程执行结束时,任务管理器显示占内存是538mb
Thread.sleep(10*1000);
}
}
class MyThread1 extends Thread
{
public void run()
{
Vector v=new Vector(99999999);
for (int i=1;i <9999999; i++)
{
Object o=new Object();
v.add(o);
}
}
}
class MyThread2 extends Thread
{
public void run()
{
System.gc();
}
}
第一个线程之后 程序占内存529mb
而同样的 第三个线程执行结束之后程序占内存 538mb 而不是 529mb+529mb 为什么?
这种现象是说明 第二个线程执行 gc()起作用了?
我曾经写过一个定时程序(有一个死循环,类似长期驻守的服务程序)
每循环一次程序占用的内存都要多一些,这样循环几次内存就溢出了
但是理论上每循环一次 都是一个全新的过程,如果内存能及时回收的话应该没问题
我的困惑就来源于此,那位高手能解答一下
------解决方案--------------------呵呵~这个问题很严重!
JAVA的内存回收机制只是针对已经执行结束的线程进行回收处理
而一个线程无限制的循环,这说明这个线程还没有执行完毕,至于你强制回收也不起作用
因为它就没有执行完毕!
所以该线程无限制的申请内存,知道服务器内存耗尽,VM就会抛出
OutOfMemoryError 异常
上面的代码你是在考验电脑的性能吧,线程的执行也是随机的,如果不休眠的话,那个先执行完谁也不知道,如果你强制sleep()的话,那也说不定,那只代表睡了一会儿觉,我这样说不知道你能明白吗~
------解决方案--------------------学习!
------解决方案--------------------我想楼主没有搞清楚GC的执行原理吧,有两点你必须明确:
1.GC执行的时间:在你的程序执行的时候消耗内存超过了JVM分配的初始内存,才开始执行,你可以在你的代码中重写finalize()来证明.
2.GC只回收你程序中那些垃圾,就是你没有使用的对象所占的空间.
看看你的程序:
Vector v=new Vector(99999999);
for (int i=1;i <9999999; i++)
{
Object o=new Object();
v.add(o);
}
每个对象都有变量指,GC什么都回收不了.
------解决方案--------------------调用gc()只是通知JVM需要回收垃圾,至于具体什么时间回收,由JVM的算法决定。java中没有强制回收垃圾的方法
------解决方案--------------------同意 chuan122345(Synchronized+ObjectPool) 说的:
GC只回收垃圾对象,即没有被变量引用的那些对象。你只要将用过的对象引用及时赋值为null,GC就会在恰当的时候来回收,根本用不着你去调用什么System.gc()方法。
------解决方案--------------------一般来说
比较好的编程习惯是用完一个变量以后设置成null
Object obj;
.....
....
obj = null;
执行GC()只是告诉JVM,现在 "可以 "(不是现在必须)回收内存
JVM就算收到GC命令,如果它认为现在不需要回收,也是什么都不做的