对象保留在内存中直到强制GC

时间:2013-10-31 17:26:27

标签: java map garbage-collection concurrenthashmap

我有这样的代码:

public static class Obj {//Class within class
Long a;

}

private static final Map<String, Obj> map = new ConcurrentHashMap<>();

public static void main(String[] args)
{
    for(long l = 0;l<10000090L;l++)
    {
        Obj o = new Obj();
        o.a = l;
        map.put("asd", o);
        map.remove("asd");
    }
}

在我的电脑上,我已经在线程中添加了这段代码 - 所以我可以很容易地看到内存使用情况。我已经开始使用Your Kit Java Profiler进行概要分析。

我已向VM添加了其他参数:-XX:+ UseConcMarkSweepGC -XX:+ UseTLAB -XX:+ CMSIncrementalMode -XX:+ CMSIncrementalPacing

我测试此程序的结果: 循环之前您的工具包显示 - 用户Par服务空间0字节,用户标准Eden空间12 MB,使用CMS旧Gen 0字节 战斗机你的工具包显示后 - 用户Par Serivce Space 8 KB,用户Par Eden Space 38 mb,二手CMS旧Gen 0字节1,6 mb

然后我强迫垃圾收集器,结果: 你的套件显示 - 用户Par Serivce Space 0字节,用户Par Eden Space 1,4 mb,二手CMS Old Gen 1,5 mb

因此,如果我正确读取此值,Obj或“asd”将保留在内存中,直到完全垃圾收集器。 是否有任何方法可以实时删除这些对象而无需等待垃圾收集器检查是否可以访问程序中的每个对象?

2 个答案:

答案 0 :(得分:2)

垃圾收集器是唯一从内存中删除对象的东西。您可以随时调用System.gc(),这要求垃圾收集器尽快运行,而不是稍后运行。但通常情况下,没有必要。在程序遇到内存问题之前,垃圾收集器将自行运行。

答案 1 :(得分:2)

垃圾收集器会在需要时跳转,在大多数情况下,它会在最优化的时间跳转。使用System.gc()手动请求GC触发可能根本没有优势。

此外,你怎么知道“abj”是否一直待到完全gc。您的伊甸园一代占用了38 MB的空间,老一代占用了0 MB。在你的情况下只有短寿命对象是预期的行为(通常小的gc应该工作,除非你以非常快的速度插入并且eden很快填满)