윈도우 10에 아래의 코드를 실행 / 오픈 JDK 11.0.4_x64는 출력으로 생산 used: 197
하고 expected usage: 200
. 이는 백만 개의 요소로 구성된 200 바이트 배열이 대략적으로 사용됨을 의미합니다. 200MB RAM. 다 괜찮아.
I로부터 코드에서 바이트 배열의 할당을 변경하는 경우 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으로 조금 더 깊이 살펴보면 첫 번째 경우 모든 것이 예상대로 보입니다.
두 번째 경우에는 바이트 배열 외에도 바이트 배열과 동일한 양의 RAM을 차지하는 동일한 수의 int 배열이 표시됩니다.
그런데이 int 배열은 참조 된 것을 나타내지 않지만 가비지 수집 할 수는 없습니다 ... (바이트 배열은 참조 된 곳에서 잘 나타납니다.)
어떤 아이디어가 여기서 일어나고 있습니까?
int[]
을 위해 큰 에뮬레이션을 사용하여 내부적으로 JVM과 관련이 byte[]
있습니까?