Ile on waży?!

blog.lantkowiak.pl 7 lat temu

Czy zastanawialiście się kiedyś jak dużo pamięci zajmują obiekty w Javie? Dużo osób pewnie nigdy się nad tym nie głowiło, a przynajmniej nie przed pierwszym OutOfMemoryError

W tym wpisie postaram się pokazać w jaki sposób oszacować wielkość obiektów, które tworzymy w Javie.

Typy prymitywne

Niewątpliwie najłatwiej jest określić ilość pamięci zajmowanej przez typy prymitywne. Poniżej przedstawiam tabelkę, która pokazuje ile każdy z typów potrzebuję bajtów w pamięci.

Typbajty
boolean1
byte1
char2
int4
float4
long8
double8

Ilość pamięci potrzebnej do przechowywania booleana może trochę dziwić. W końcu może on przyjąć tylko dwa wartości i w teorii powinien zajmować 1 bit. Specyfikacja JVM nie definiuje ile pamięci jest potrzebne na przechowanie booleana i zależy to od danej implementacji. Dla uproszczenia możemy śmiało przyjąć, iż jest potrzebny 1 bajt.

Reszta wartości wydaję się być w miarę oczywista

Tablice

Każda tablica zajmuje wielokrotność danego typu (co wydaję się oczywiste ;)) oraz dodatkowe 24 bajty, które są narzutem tablicy. Poniżej przedstawiam tabelkę z przykładami, które powinny wszystko wyjaśnić.

Typbajty
byte[]N + 24
char[]2N+24
int[]4N+24
double[]8N+24

Obiekty

I teraz przechodzimy do mięsa tematu – czyli jak oszacować wielkość obiektu naszej klasy.

Aby to zrobić potrzebujemy kilku dodatkowych informacji.

Narzut obiektu

Każdy obiekt, podobnie jak tablica, powoduje dodatkowy narzut pamięci. W tym przypadku jest to 16 bajtów.

Referencja

Każda przetrzymywana referencja w naszym obiekcie to dodatkowe 8 bajtów.

Padding

Wielkość każdego obiektu jest uzupełniana do wielokrotności 8 bajtów.

Praktyka

Jako przykład weźmy klasę String. Poniżej przedstawiam wycinek implementacji tej klasy, który jest potrzebny do oszacowania wielkości obiektu.

public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; private final int offset; private final int count; private int hash; ... }

Do obliczenia potrzebujemy zsumować kilka rzeczy:

  1. Narzut obiektu – 16 bajtów
  2. Referencja do tablicy – 8 bajtów
  3. Tablica – 2N + narzut tablicy 24 bajty
  4. Pole offset – 4 bajty
  5. Pole count – 4 bajty
  6. Pole hash – 4 bajty

Zsumowując wszystko wychodzi nam 2N + 60 bajtów. W takim przypadku musimy jeszcze pamiętać o paddingu, czyli dodajemy 4 bajty, aby całkowita wielkość obiektu była wielokrotnością 8.

Podsumowanie

Powyżej przedstawiłem ogólne zasady, których możemy użyć, aby oszacować wielkość naszych obiektów w Javie. Dzięki temu możemy lepiej zrozumieć co jest alokowane w pamięci i jaki rozmiar zajmuje.

Idź do oryginalnego materiału