Java'da Object Layout Optimizasyonu

Java, diger bir suru dilde oldugu gibi, objelerin calisma zamaninda cache'e daha duzgun alinmasi ve VM'in bellek yonetimini daha duzgun yapabilmesi icin bazi object layout optimizasyonlari yapar.

Object layout optimizasyonu, objenin bellekteki yapisinin yukaridaki saydigim sebeplerden dolayi, bizim yazdigimiz halden biraz daha degisik olmasi demek :). Bu yapi temelde 3 kisimdan olusur;

  1. Header: Objeyle ilgili metadatanin tutuldugu alan. hashCode()'dan donen garip sayi, obje uzerindeki lock bilgisi gibi JVM'in isine yarayan bilgiler burada tutulur.
  2. Objenin icindeki alanlar: Bunlar datayi tutan kisimlar.
  3. Padding alanlari: Bunlar da JVM'in optimizasyon icin objenin sonuna ya da ortasina koydugu bos alanlar.

(Bunlari incelemek icin, bagimsiz bir proje olarak baslayip sonradan OpenJDK icine dahil edilmis JOL'u kullaniyorum)

Diyelim ki asagidaki gibi bir sinif var

Bunun bellekteki yapisina bakinca asagidaki gibi oldugu goruluyor;

Baslangic adresi boyut alan
0 12 (object header)
12 1 boolean A.a
13 3 (loss due to the next object alignment)

Kodu calistiran JVM'in tipine gore header alaninin buyuklugu ve objelerin kacar byte'lik bloklar seklinde tutulacagi (bu ornekte 8 byte) farklilik gosterebilir.

Yukaridaki ornek cok sacma gorunuyor. Yani biri neden tek boolean alani icin bir class olustursun diyoruz ama aslinda bu basit siniflar bizim surekli olarak kullandigimiz, hatta Java Generics ile birlikte daha da cok kullandigimiz (Stream, Optional gibi yapilar, Lombok vs.) Integer, Long gibi primitive wrapper siniflara denk geliyor.

Son olarak asagidaki gibi kodun ciktisinda aradaki fark gorulebilir.

arrayOfObjects  24M byte yer kaplarken arrayOfLongs  8M byte yer kapliyor.

Buraya kadar cok da olaganustu bir sey yok aslinda. Bir sonraki post'ta inheritance nasil calisiyor onu yazayim. JVM'in asil cuvalladigi kisim orasi :)