我正在尝试编写一个应该占用特定大小内存的程序。我想知道的一个问题是,当堆中实际有空闲空间时,我得到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();
}
}
}
启动它的命令:
java -Xmx4096m MemoryEater1 3000
输出:
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)
最大内存和总内存之间的差异是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
为什么会这样?
答案 0 :(得分:1)
我不会认为它是碎片,因为你只有一个线程分配内存而不回收任何东西。
它是您的特定垃圾收集器,它们以不同方式管理内存,导致您的应用程序或多或少无法使用。您可以通过分析java -XX:+PrintCommandLineFlags
)的输出找出使用的是哪一个。
您可以尝试使用不同管理内存的G1。
java -Xmx4096m -XX:+UseG1GC MemoryEater1 3000
或玩一代尺寸,例如-XX:NewSize
等等。
有关更多信息,请阅读here以及有关垃圾收集器算法的任何内容,例如: [GC调整]
这里快速说明了为不同代人分割内存如何使其无法使用(VM options)。 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
答案 1 :(得分:0)
可以将JVM标志设置为大于计算机上物理内存的内存量。根据目前给出的信息,您似乎很可能缺少分配此阵列的物理内存。换句话说,JVM从操作系统请求更多内存,操作系统说没有可用的内存。
另一种可能性是在您的问题的评论中注明了内存碎片问题。但是,在这种情况下,由于程序的结构,我认为不太可能。我不认为可以排除它。