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()起作用了?我曾经写过一个定时程序(有一个死循环,类似长期驻守的服务程序)
每循环一次程序占用的内存都要多一些,这样循环几次内存就溢出了
但是理论上每循环一次 都是一个全新的过程,如果内存能及时回收的话应该没问题我的困惑就来源于此,那位高手能解答一下

解决方案 »

  1.   

    呵呵~这个问题很严重!JAVA的内存回收机制只是针对已经执行结束的线程进行回收处理而一个线程无限制的循环,这说明这个线程还没有执行完毕,至于你强制回收也不起作用因为它就没有执行完毕!所以该线程无限制的申请内存,知道服务器内存耗尽,VM就会抛出 OutOfMemoryError 异常上面的代码你是在考验电脑的性能吧,线程的执行也是随机的,如果不休眠的话,那个先执行完谁也不知道,如果你强制sleep()的话,那也说不定,那只代表睡了一会儿觉,我这样说不知道你能明白吗~
      

  2.   

    我想楼主没有搞清楚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什么都回收不了.
      

  3.   

    调用gc()只是通知JVM需要回收垃圾,至于具体什么时间回收,由JVM的算法决定。java中没有强制回收垃圾的方法
      

  4.   

    同意 chuan122345(Synchronized+ObjectPool) 说的:GC只回收垃圾对象,即没有被变量引用的那些对象。你只要将用过的对象引用及时赋值为null,GC就会在恰当的时候来回收,根本用不着你去调用什么System.gc()方法。
      

  5.   

    一般来说
    比较好的编程习惯是用完一个变量以后设置成null
    Object obj;
    .....
    ....
    obj = null;执行GC()只是告诉JVM,现在"可以"(不是现在必须)回收内存
    JVM就算收到GC命令,如果它认为现在不需要回收,也是什么都不做的