Windowsの10の下のコードを実行している/ OpenJDKの11.0.4_x64は出力として生成used: 197
とexpected usage: 200
。これは、100万要素の200バイト配列が約100を占めることを意味します。200MB RAM。すべて元気です。
コード内のバイト配列割り当てを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で少し深く見ると、最初のケースではすべてが期待どおりに表示されます。
2番目のケースでは、バイト配列に加えて、バイト配列と同じ量のRAMを使用する同じ数のint配列が表示されます。
ちなみに、これらのint配列は、それらが参照されていることを示していませんが、ガベージコレクションはできません...
ここで何が起こっているのでしょうか?
int[]
せるために大きなものをエミュレートするbyte[]
ために内部でJVMを使用することに何か関係があるのでしょうか?