Java 8 与 Java 9 之间的内存分配是否存在差异?
Are there differences in memory allocation between Java 8 vs. Java 9?
我想试验 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 = 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 选项的程序时,我注意到 Java 8 (1.8.0.131) 和 Java 9 (9.0. 1).
Java 8 的效果接近我的预期。当我 运行 使用 -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
然而,当我 运行 与 Java 9 相同的程序时,它只得到大约 一半 (127 MiB) 在我得到异常之前。这是一致的。如果我将 -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
我在文档中搜索了 Java 8 和 Java 9 之间内存管理的任何变化,但没有找到任何东西。
有没有人知道为什么 Java 9 在某些情况下 manage/allocate 的记忆与以前的 Java 版本不同?
我发现 this 一篇关于 Java 9 计划如何以不同方式进行垃圾收集的非常有趣的文章。
更具体地说,Java9 计划使用 G1 垃圾收集器,它将内存划分为固定大小。您的代码可能正在做的是触发内存分成两个固定大小的块,用于 Java 9。这样做的原因是它会节省另一半内存用于移动所有内容和 'compacting'内存仍在使用中。但是,因为您只是继续使用内存,所以当使用了 ~1/2 内存时它会立即中断。我不确定你的 CS 有多严格,但在我的学校我们研究了简单的垃圾技术,G1GC 让我想起的一个如此简单的技术是 stop-and-copy 技术,它在两半之间切换分配的内存内存,而它 'compacts' 内存,因为它这样做。
在Java8中,使用了Parallel Collector,它与G1GC不同,它只关心吞吐量。因此,接近 100% 的真实堆将被使用,代价是更长的 GC 时间。当然,这是两个版本之间的权衡,但您可以通过明确指定要使用的 GC 类型来解决这个问题。例如,如果在 Java 9 上,您使用选项:
-XX:UseParallelGC
您应该看到与使用 Java 时相同的行为 8. 我链接的文章有所有不同的选项,但我想您明白了。希望这个 helps/answer 你的问题,直到你提出来我才意识到这一点,所以谢谢你让我意识到这一点。
编辑: 根据 Oracle 他们自己的说法,他们说新的 G1 垃圾收集器是为高内存机器设计的,再次给出了他们不使用满堆 space 以减少 GC 时间。
我想试验 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 = 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 选项的程序时,我注意到 Java 8 (1.8.0.131) 和 Java 9 (9.0. 1).
Java 8 的效果接近我的预期。当我 运行 使用 -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
然而,当我 运行 与 Java 9 相同的程序时,它只得到大约 一半 (127 MiB) 在我得到异常之前。这是一致的。如果我将 -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
我在文档中搜索了 Java 8 和 Java 9 之间内存管理的任何变化,但没有找到任何东西。
有没有人知道为什么 Java 9 在某些情况下 manage/allocate 的记忆与以前的 Java 版本不同?
我发现 this 一篇关于 Java 9 计划如何以不同方式进行垃圾收集的非常有趣的文章。
更具体地说,Java9 计划使用 G1 垃圾收集器,它将内存划分为固定大小。您的代码可能正在做的是触发内存分成两个固定大小的块,用于 Java 9。这样做的原因是它会节省另一半内存用于移动所有内容和 'compacting'内存仍在使用中。但是,因为您只是继续使用内存,所以当使用了 ~1/2 内存时它会立即中断。我不确定你的 CS 有多严格,但在我的学校我们研究了简单的垃圾技术,G1GC 让我想起的一个如此简单的技术是 stop-and-copy 技术,它在两半之间切换分配的内存内存,而它 'compacts' 内存,因为它这样做。
在Java8中,使用了Parallel Collector,它与G1GC不同,它只关心吞吐量。因此,接近 100% 的真实堆将被使用,代价是更长的 GC 时间。当然,这是两个版本之间的权衡,但您可以通过明确指定要使用的 GC 类型来解决这个问题。例如,如果在 Java 9 上,您使用选项:
-XX:UseParallelGC
您应该看到与使用 Java 时相同的行为 8. 我链接的文章有所有不同的选项,但我想您明白了。希望这个 helps/answer 你的问题,直到你提出来我才意识到这一点,所以谢谢你让我意识到这一点。
编辑: 根据 Oracle 他们自己的说法,他们说新的 G1 垃圾收集器是为高内存机器设计的,再次给出了他们不使用满堆 space 以减少 GC 时间。