我在分配和释放字节数组时遇到OutOfMemoryError java堆异常,即使有足够的可用内存用于分配.下面有一个简短的日志.我知道从不同的JVM上运行,问题是由于内存碎片造成的,最大的空闲块只有大约6MB.我认为java(oracle)JVM应该处理碎片化的内存.
这是我的测试:
这是我的详细信息:
Total Free Memory: 9881728
Attempting to Allocate Array of size: 6917209
Freeing Allocated Array of size: 6917209
Total Free Memory: 9881728
Attempting to Allocate Array of size: 6917209
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Run Code Online (Sandbox Code Playgroud)
我正在运行的另一个JVM是Skelmir的CEE-J,我在低内存设备上运行,所以我无法设置MaxPermSize.有趣的是,java堆被拆分成不同的区域,这些区域可以在垃圾收集后改变大小吗?我已经运行了另外的测试我在哪里,首先为大约95%的内存创建一个字节数组,然后再次释放数组,然后我创建了一个包含散列图的对象数组,每个散列图都有一个条目,我清除了数组和映射,然后再次重新分配相同的数组.
我每次分配和释放时检查内存.这样做了10次之后,我最后一次释放内存,然后我检查内存,看到我有完整的JVM分配,然后我尝试再次分配95%的JVM分配并获得相同的JVM内存异常,即使它说我有足够的内存来分配?
public static void main(String[] args) throws InterruptedException {
Runtime s_runtime = Runtime.getRuntime ();
long used_memory = s_runtime.totalMemory () - s_runtime.freeMemory ();
long start_memory = used_memory;
long freeMemory = s_runtime.freeMemory();
Integer numSubMemories = 1;
Integer numMapEntries = 1;
Integer numIterations = 1;
float percentMem = (float) 1.0;
if(args.length>0){
if(args[0]!=null){
String subEntries = args[0];
if(subEntries.length()>0){
numSubMemories = Integer.parseInt(subEntries);
}
}
if(args[1]!=null){
String mapEntries = args[1];
if(mapEntries.length()>0){
numMapEntries = Integer.parseInt(mapEntries);
}
}
if(args[2]!=null){
String numIts = args[2];
if(numIts.length()>0){
numIterations = Integer.parseInt(numIts);
}
}
if(args[3]!=null){
String percentMemArg = args[3];
if(percentMemArg.length()>0){
percentMem = Float.parseFloat(percentMemArg);
}
}
}
System.out.println("Total Free Memory: " + freeMemory);
int numBytes = (int) (freeMemory * percentMem);
System.out.println("Attempting to Allocate Array of size: " + numBytes);
byte[] mbyteArray = new byte[numBytes];
System.out.println("Freeing Allocated Array of size: " + numBytes);
mbyteArray = null;
TestMemory myMemory = new TestMemory(numSubMemories,numMapEntries);
used_memory = s_runtime.totalMemory () - s_runtime.freeMemory ();
System.out.println("Used Memory: " + used_memory);
long after_allocation_memory = used_memory;
for(int i=0;i<numIterations;i++){
System.out.println("\t\t--Iteration: "+ i + " about to release Memory");
myMemory.releaseMemoryArray(numSubMemories);
System.out.println("\t\t--Iteration: "+ i + " about to reallocate Memory");
myMemory.reAllocateMemoryArray(numSubMemories,numMapEntries);
used_memory = s_runtime.totalMemory () - s_runtime.freeMemory ();
System.out.println("\t\t--Used Memory: " + used_memory);
System.out.println("\t\t--Max Memory: " + s_runtime.maxMemory());
System.out.println("\t\t--Free Memory: " + s_runtime.freeMemory());
System.gc();
System.out.flush();
}
System.out.println("Releasing the Arrays for the last time");
myMemory.releaseMemoryArray(numSubMemories);
System.gc();
freeMemory = s_runtime.freeMemory();
//numBytes = (int)(freeMemory*0.95);
System.out.println("Attempting to Allocate Array of size: " + numBytes);
System.out.println("Total Free Memory: " + freeMemory);
mbyteArray = new byte[numBytes];
long end_memory = used_memory;
//System.gc();
Thread.sleep(6000);
used_memory = s_runtime.totalMemory () - s_runtime.freeMemory ();
System.out.println("------Results---------");
System.out.println(" Start Memory: " + start_memory);
System.out.println(" After Memory: " + after_allocation_memory);
System.out.println(" End Memory: " + end_memory);
System.out.println("End Release Memory: " + used_memory);
}
Run Code Online (Sandbox Code Playgroud)
从第二次测试输出日志.总可用内存:9881728尝试分配大小数组:6917209释放已分配大小的数组:6917209已用内存:7519744 - 迭代:0即将释放内存 - 迭代:0即将重新分配内存 - 使用内存:7890928 -Max内存:10092544 -Free Memory:2147808 -Iteration:1即将发布内存-Iteration:1即将重新分配内存 - 使用内存:930952 -Max内存:10092544 -Free内存:9107792 -Iteration:2即将发布内存-Iteration:2即将发布重新分配内存使用内存:1181832 -Max内存:10092544 -Free内存:8856912 -Iteration:3即将释放内存-Iteration:3即将重新分配内存-Used内存:1190552 -Max内存:10092544 -Free内存:8848192 -Iteration :4即将释放内存 - 迭代:4即将重新分配内存 - 使用内存:902408 -Max内存:10092544 -Free内存:9190136 -Iteration:5即将释放内存-Iteration:5即将重新分配内存-Used Memory:902408 -Max Memory:10092544 -Free Memory:919013 6 - 迭代:6即将释放内存 - 迭代:6即将重新分配内存 - 使用内存:902408 -Max内存:10092544 -Free内存:9190136 -Iteration:7即将释放内存-Iteration:7即将重新分配内存-Used内存:902408 -Max内存:10092544 -Free内存:9190136 -Iteration:8即将释放内存-Iteration:8即将重新分配内存-Used Memory:902408 -Max内存:10092544 -Free内存:9190136 -Iteration:9即将发布release Memory -Iteration:9即将重新分配内存 - 使用内存:902408 -Max内存:10092544 -Free内存:9190136最后一次释放数组尝试分配大小的数组:6917209总可用内存:9956688线程中的异常"main "java.lang.OutOfMemoryError:Java堆空间
Java 堆被分为多个区域。单个分配不能跨越区域。Oracle JRE 中有多种-XX允许配置分配的选项 [我将让其他人指出详细信息]。您可以将伊甸园和幸存者区域设置得非常小。另一个问题是,如果收集后可用内存不足,您可能仍然会收到 OOME 来防止抖动(再次有更多-XX选项来控制)。
| 归档时间: |
|
| 查看次数: |
2492 次 |
| 最近记录: |