日期:2014-05-20  浏览次数:20821 次

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命令,如果它认为现在不需要回收,也是什么都不做的