Я получаю исключение Java-кучи OutOfMemoryError, когда просто выделяю и освобождаю байтовый массив, даже если для выделения достаточно памяти.
Ниже приведен краткий журнал. Из работы на другой JVM я знаю, что проблема связана с фрагментированной памятью и что самый большой свободный блок составляет всего около 6 МБ. Я думал, что Java (оракул) JVM должен заботиться о фрагментированной памяти.
Это мой тест:
- Настройка Java JVM с параметрами -Xms10M -Xmx10M
- Я выделяю байтовый массив, скажем, 90 процентов памяти JVM.
- Установите для этого байтового массива значение null, а затем попытайтесь перераспределить байтовый массив на 90 процентов памяти JVM.
- Из журналов видно, что память 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
Другая JVM, которую я использую, - это CEE-J от Skelmir, я работаю на устройстве с низким объемом памяти, поэтому я не могу установить 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);
}
Выходной журнал из второго теста.
Всего свободной памяти: 9881728
Попытка выделить массив размером: 6917209
Выделение выделенного массива размера: 6917209
Используемая память: 7519744
-Выполнение: 0 собирается выпустить память
-Выполнение: 0 собирается перераспределить память
Используемая память: 7890928
Макс память: 10092544
Свободная память: 2147808
-Выполнение: 1 собирается выпустить память
-Выполнение: 1 собирается перераспределить память
Используемая память: 930952
Макс память: 10092544
Свободная память: 9107792
-Выполнение: 2 о выпуске памяти
-Выполнение: 2 о перераспределении памяти
Используемая память: 1181832
Макс память: 10092544
Память: 8856912
-Выполнение: 3 о выпуске памяти
-Выполнение: 3 о перераспределении памяти
Используемая память: 1190552
Макс память: 10092544
Память: 8848192
-Выполнение: 4 о выпуске памяти
-Выполнение: 4 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
-Выполнение: 5 собирается выпустить память
-Выполнение: 5 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
-Изменение: 6 собирается выпустить память
-Выполнение: 6 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
-Изменение: 7 собирается выпустить память
-Изменение: 7 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
-Выполнение: 8 собирается выпустить память
-Выполнение: 8 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
-Изменение: 9 собирается выпустить память
-Выполнение: 9 о перераспределении памяти
Используемая память: 902408
Макс память: 10092544
Свободная память: 9190136
Выпуск Массивов в последний раз
Попытка выделить массив размером: 6917209
Всего свободной памяти: 9956688
Исключение в потоке "main" java.lang.OutOfMemoryError: пространство кучи Java