Запуск наведеного нижче коду в Windows 10 / OpenJDK 11.0.4_x64 видає як вихід used: 197
і expected usage: 200
. Це означає, що 200 байтових масивів з мільйона елементів займають приблизно. 200 Мб оперативної пам’яті. Все добре.
Коли я змінюю розподіл байтового масиву в коді з new byte[1000000]
на new byte[1048576]
(тобто на елементи 1024 * 1024), він видає як вихід used: 417
і expected usage: 200
. Якого біса?
import java.io.IOException;
import java.util.ArrayList;
public class Mem {
private static Runtime rt = Runtime.getRuntime();
private static long free() { return rt.maxMemory() - rt.totalMemory() + rt.freeMemory(); }
public static void main(String[] args) throws InterruptedException, IOException {
int blocks = 200;
long initiallyFree = free();
System.out.println("initially free: " + initiallyFree / 1000000);
ArrayList<byte[]> data = new ArrayList<>();
for (int n = 0; n < blocks; n++) { data.add(new byte[1000000]); }
System.gc();
Thread.sleep(2000);
long remainingFree = free();
System.out.println("remaining free: " + remainingFree / 1000000);
System.out.println("used: " + (initiallyFree - remainingFree) / 1000000);
System.out.println("expected usage: " + blocks);
System.in.read();
}
}
Поглянувши трохи глибше на visualvm, я бачу в першому випадку все, як очікувалося:
У другому випадку, окрім байтових масивів, я бачу таку ж кількість масивів int, що займають стільки ж оперативної пам’яті, що й байтові масиви:
До речі, ці масиви int не показують, що на них посилаються, але я не можу збирати їх сміття ... (Байтові масиви добре показують, куди вони посилаються.)
Якісь ідеї, що тут відбувається?
int[]
емуляцію великого byte[]
для кращого просторового простору?