Java 即使旧版本已满,JVM也没有OOM问题

Java 即使旧版本已满,JVM也没有OOM问题,java,jvm,Java,Jvm,我看到了一个关于JVM内存的有趣问题。这真是令人困惑。考虑这种情况:将一个新对象放进一个哈希映射,而这个对象只有一个字符串字段。它应该有一个OOM,因为我没有重写hashcode()和equals(),但结果不是这样,JVM一直在执行GC。所有对象都被HashMap强引用,为什么没有OOM public class FinalTest { private final String key; FinalTest(String key){ this.key = key

我看到了一个关于JVM内存的有趣问题。这真是令人困惑。考虑这种情况:将一个新对象放进一个哈希映射,而这个对象只有一个字符串字段。它应该有一个OOM,因为我没有重写hashcode()和equals(),但结果不是这样,JVM一直在执行GC。所有对象都被HashMap强引用,为什么没有OOM

public class FinalTest {
    private final String key;
    FinalTest(String key){
        this.key = key;
    }
    public void getKey(){
        System.out.println( key);
    }
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException{
        Map<FinalTest,String> map = new HashMap<>();
        for(;;){
            map.put(new FinalTest("a"),"v");
            System.out.println(map.toString());
        }
    }
}

公共类最终测试{
私有最终字符串密钥;
最终测试(字符串键){
this.key=key;
}
public void getKey(){
系统输出打印项次(键);
}
publicstaticvoidmain(字符串[]args)抛出NoSuchFieldException、IllegalAccessException{
Map Map=newhashmap();
对于(;;){
地图出售(新的最终测试(“a”),“v”);
System.out.println(map.toString());
}
}
}
jconsole屏幕截图:

然后我删除了打印命令,结果不一样

旧版本用法:

由于伊甸园空间被清除,曲线在最后一刻下降。然后看起来进程被阻塞(旧的Gen已满)。此外,即使旧的gen已满,它仍然不会生成OOM异常


为什么这两种情况不同?为什么没有OOM异常?

对于循环的每次迭代,
map.toString()
分配的内存块比
map.put(新的FinalTest(“a”),“v”)大得多
没有,因此toString隐藏map.put分配的效果

因此,堆内存图显示了大量的峰值,因为有大量的字符串是可垃圾回收的

更改日志行以打印大小,您将看到map.put()调用逐渐消耗所有可用内存,在收集integer->string堆时,每个GC的更改越来越少:

 System.out.println(map.size());

一旦您按照上述方式进行更改或注释掉
System.out.println
,运行速度将提高,因为需要的GC要少得多,您将获得
java.lang.OutOfMemoryError:java堆空间

对于循环的每个迭代,
map.toString()
分配的内存块比map.put(新的FinalTest(“a”),“v”)没有,因此toString隐藏map.put分配的效果

因此,堆内存图显示了大量的峰值,因为有大量的字符串是可垃圾回收的

更改日志行以打印大小,您将看到map.put()调用逐渐消耗所有可用内存,在收集integer->string堆时,每个GC的更改越来越少:

 System.out.println(map.size());

一旦您按照上述方式进行更改或注释掉
System.out.println
,运行速度将提高,因为需要的GC要少得多,您将获得
java.lang.OutOfMemoryError:java堆空间

您如何知道旧版本已满?@gudok在右下角的最后一张图片中,堆使用率表的第一列表示使用了多少旧的gen空间。您如何知道旧的gen已满?@gudok在最后一张图片的右下角,堆使用率表的第一列表示使用了多少旧的gen空间。