我正在尝试编写一个应该占用特定大小内存的程序.我想知道的一个问题是,outOfMemory当堆中实际存在空闲空间时,我会遇到异常.
这是代码:
import java.util.Vector;
import java.lang.*;
public class MemoryEater1 {
public static void main(String[] args) {
try {
long mb = Long.valueOf(args[0]);
Vector v = new Vector();
Runtime rt = Runtime.getRuntime();
while (true) {
if (v.size() > 0) {
if (((long) v.size())*100 < mb) {
System.out.println("total memory: " + rt.totalMemory()/1024/1024);
System.out.println("max memory: " + rt.maxMemory()/1024/1024);
System.out.println("free memory: " + rt.freeMemory()/1024/1024);
System.out.println("Trying to add 100 mb");
//100mb
byte b[] = new byte[104857600];
v.add(b);
}
} else {
//100mb
byte b[] = new byte[104857600];
v.add(b);
System.out.println("Added 100 mb");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
启动它的命令:
java -Xmx4096m MemoryEater1 3000
Run Code Online (Sandbox Code Playgroud)
并输出:
total memory: 2867
max memory: 3641
free memory: 59
Trying to add 100 mb
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryEater1.main(MemoryEater1.java:18)
Run Code Online (Sandbox Code Playgroud)
那么最大内存和总内存之间的差异是774mb,这应该足以消耗100mb以上,但仍然存在错误,甚至机器资源足够:
[user@machine ~]$ free -m
total used free shared buffers cached
Mem: 15950 3447 12502 0 210 2389
-/+ buffers/cache: 847 15102
Swap: 4031 1759218603 8941
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
我不认为这是碎片,因为你只有一个线程分配内存而不回收任何东西。
这要归咎于您的特定垃圾收集器,它们以不同的方式管理内存,从而或多或少地导致您的应用程序不可用。您可以通过分析 ) 的输出来找出使用的是哪一个java -XX:+PrintCommandLineFlags。
您可以尝试使用 G1,它以不同的方式管理内存。
java -Xmx4096m -XX:+UseG1GC MemoryEater1 3000
Run Code Online (Sandbox Code Playgroud)
或者玩弄生成大小,例如-XX:NewSize等等。
有关更多信息,请阅读VM 选项和有关垃圾收集器算法的任何内容,例如 [GC 调整]
下面是一个快速说明,将内存分割为不同的代会如何使其不可用(http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html)。
