Kod u dołu tego pytania jest nieco długi, ale w zasadzie tworzy kilka obiektów i określa ich rozmiar w pamięci. I wykonanie kodu z następujących parametrów JVM (TLAB uniknąć alokacji pamięci kawałek i podobno uzyskać dokładne dane użycia pamięci):Dokładny pomiar wielkości obiektów
-server -Xms2000m -Xmx2000m -verbose:gc -XX:-UseTLAB
uruchomić kod na 64 bitowym Hotspot JVM i uzyskać następujące dane wyjściowe:
Java Internetu (TM) 64-bitowego serwera VM
obiekt 16 bajtówobiektu z 1 int 16 bajtów
obiektu 2 wskazówki: 24 bajty
obiektu z 3 wskazówki: 24 bajtówobiektu z 1 długi: 24 bajty
obiektu 2 długościami: 32 bajtów
obiektu z 3 długościami: 40 bajtówobiektu z 1 odnośnik 16 bajtów
obiekt 2 publikacjach: 24 bajtów
przedmiot z 3 publikacjach: 24 bajtów
że wnioski:
- Obiekt zajmuje 12 bajtów, wyrównanych do 16 bajtów.
- int trwa 4 bajty (1 obiekt z jednym int 12 + 4 = jeszcze 16 bajtów, z 2 wskazówki: 12 + 8 = 20 dostosowane do 24 bajtów)
- długo trwa 8 bajtów (1 przedmiotu z jednego długi jest 12 + 8 = 20 bajtów, wyrównane do 24 bajtów)
Ale ja usiłuję zrozumieć dlaczego odniesienia nie używać tak dużo miejsca jak long
s.
Ponieważ referencje mają 8 bajtów na 64-bitowej maszynie JVM, oczywistym wnioskiem jest to, że metodologia pomiaru ma wadę *. Czy możesz wyjaśnić, co się dzieje i co można zrobić, aby to naprawić?
* Uwagi:
- brak biegnie GC podczas pomiaru.
- używanie profilera Netbeans daje podobne wyniki.
public class TestMemoryReference {
private static final int SIZE = 100_000;
private static Runnable r;
private static Object o = new Object();
private static Object o1 = new Object();
private static Object o2 = new Object();
private static Object o3 = new Object();
public static class ObjectWith1Int { int i; }
public static class ObjectWith2Ints { int i, j; }
public static class ObjectWith3Ints { int i, j, k; }
public static class ObjectWith1Long { long i; }
public static class ObjectWith2Longs { long i, j; }
public static class ObjectWith3Longs { long i, j, k; }
public static class ObjectWith1Object { Object o = o1; }
public static class ObjectWith2Objects { Object o = o1; Object p = o2; }
public static class ObjectWith3Objects { Object o = o1; Object p = o2; Object q = o3; }
private static void test(Runnable r, String name, int numberOfObjects) {
long mem = Runtime.getRuntime().freeMemory();
r.run();
System.out.println(name + ":" + (mem - Runtime.getRuntime().freeMemory())/numberOfObjects + " bytes ");
}
public static void main(String[] args) throws Exception {
System.out.println(System.getProperty("java.vm.name") + " ");
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new Object(); } };
test(r, "Object", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Int(); } };
test(r, "Object with 1 int", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Ints(); } };
test(r, "Object with 2 ints", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Ints(); } };
test(r, "Object with 3 ints", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Long(); } };
test(r, "Object with 1 long", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Longs(); } };
test(r, "Object with 2 longs", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Longs(); } };
test(r, "Object with 3 longs", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Object(); } };
test(r, "Object with 1 reference", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Objects(); } };
test(r, "Object with 2 references", SIZE);
r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Objects(); } };
test(r, "Object with 3 references", SIZE);
}
}
Aargh - Myślałem, że 'UseCompressedOops' domyślnie false - okazuje się, że jest włączona domyślnie. Dobrze zauważony. – assylias
@assylias: Zobacz moją edycję, aby włączyć/wyłączyć. –