Java 8和Java 9之间的内存分配是否存在差异?
我想在Java中尝试使用-Xmx选项,并创建了一个简单的测试程序,该程序在内存耗尽之前分配1个MibJava 8和Java 9之间的内存分配是否存在差异?,java,memory,memory-management,dynamic-memory-allocation,Java,Memory,Memory Management,Dynamic Memory Allocation,我想在Java中尝试使用-Xmx选项,并创建了一个简单的测试程序,该程序在内存耗尽之前分配1个Mib import java.util.Vector; public class MemoryMuncher { static final int MiB = 1048576; static final int accellerator = 1; public static void main(String[] args) { Vector victor =
import java.util.Vector;
public class MemoryMuncher {
static final int MiB = 1048576;
static final int accellerator = 1;
public static void main(String[] args) {
Vector victor = new Vector();
int i = 1;
try {
while (true) {
byte roger[] = new byte[MiB * accellerator];
victor.add(roger);
Runtime rt = Runtime.getRuntime();
System.out.printf("free: %,6d\t\ttotal: %,6d\t\tallocated: %,6d \n", rt.freeMemory()/MiB, rt.totalMemory()/MiB, i++*accellerator);
}
} catch (OutOfMemoryError e) {
System.out.println(e);
}
}
}
当我使用-Xmx选项运行程序时,我注意到Java8(1.8.0.131)和Java9(9.0.1)之间的行为差异
Java8的工作原理与我的预期非常接近。当我使用-Xmx256M运行程序时,它会在抛出OutOfMemoryError之前分配233MiB
free: 361 total: 368 allocated: 1
free: 360 total: 368 allocated: 2
...
free: 12 total: 245 allocated: 232
free: 11 total: 245 allocated: 233
java.lang.OutOfMemoryError: Java heap space
但是,当我使用Java9运行同一个程序时,在得到异常之前,它只运行了大约一半(127MIB)。这是一致的。如果我将-Xmx更改为512M或1024M,则只得到该数量的一半(分别为255 MiB和510 MiB)。我对这种行为没有任何解释
free: 250 total: 256 allocated: 1
free: 247 total: 256 allocated: 2
...
free: 2 total: 256 allocated: 126
free: 1 total: 256 allocated: 127
java.lang.OutOfMemoryError: Java heap space
我在文档中搜索了Java8和Java9之间内存管理方面的任何更改,但没有找到任何内容
有人知道为什么Java 9在某些情况下会以与以前的Java版本不同的方式管理/分配内存吗?我发现了一篇关于Java 9如何以不同方式进行垃圾收集的非常有趣的文章
更具体地说,Java9计划使用G1垃圾收集器,它将内存划分为固定大小。您的代码可能会触发内存拆分为两个固定大小的Java 9块。这样做的原因是,它将节省另一半内存,用于移动所有内容和“压缩”仍在使用的内存。但是,因为您只是一直在使用内存,所以当使用了约1/2内存时,它会立即中断。我不确定你的CS有多严格,但在我的学校我们学习了简单的垃圾技术,G1GC让我想到的一个简单的技术是在内存的一半之间切换分配的内存,同时“压缩”内存
在Java8中,使用了并行收集器,这与G1GC不同,因为它只关心吞吐量。因此,将使用接近100%的真实堆,代价是更长的GC时间。当然,这是两个版本之间的折衷,但是您可以通过显式指定要使用的GC类型来解决这个问题。例如,如果在Java 9上使用以下选项:
-XX:UseParallelGC
您应该看到与Java8相同的行为。我链接的那篇文章有各种不同的选择,但我想你明白了。希望这有助于/回答你的问题,事实上,直到你提出这一点,我才意识到这一点,所以感谢你让我意识到这一点
编辑:根据他们自己的说法,他们说新的G1垃圾收集器是为高内存机器设计的,再次说明了为什么他们不会利用整个堆空间来减少GC处理时间。为什么您关心Java 9?是的。Java11已经过时了。您是否在Java10和/或Java11早期版本中观察到了相同的行为?我确实在Java10中看到了相同的情况。我在示例中使用了Java9,因为这就是更改的开始。非常好的解释。尽管对你的答案有点质疑:在Java9中,如果我一次分配1MB,当大约一半的内存被使用时,我的内存就用完了。所以,如果我有256个MiB,它会停在126个MiB。但是,当我一次分配2MB时,168 Mib的内存就用完了。如果我分配3,它将停止在189 Mib。我想你已经找到了根本原因,这一定是由于gc的细节。是的,我想这个行为比我描述的更复杂。我认为真正完全理解g1gc工作原理的唯一方法是查看代码本身。