Thursday, July 27, 2017

Java'da Nesnelerin Belleğe Yerleşimi


Java nesneleri her zaman Heap'de yaratılır. Nesne yaratmak için new operatöründen yararlanıyoruz. Ancak nesneye artık ihtiyacımız kalmadığında, C++'da olduğu gibi delete operatörü ile geri vermemiz gerekmez. Nesnenin referans değişkenleri ile bağlantısını koparmamız yeterli olur. Heap'i çöp toplayıcı yönetir ve çalıştığında tüm ayakta kalan, canlı, hala erişilebilen nesneleri yeniden bellekte yeniden düzenler. Bilinenin aksine çöp toplayıcı ölü nesneler için herhangi bir işlem yürütmez. Çöp toplayıcı her ne yapıyor ise canlı nesneler için yapar. Dolayısı ile bellekte az yer kaplayan ve kısa ömürlü nesneler yaratmanın Java'da bir maliyeti yoktur. Benzer şekilde C++ ile karşılaştırıldığında, Java'da new ile bellek alanı ayırmak da daha hızlıdır. 

Heap tek düze ve yekpare bir alan değildir. Farklı kuşaktan nesnelerin yaşadığı özelleşmiş alanlardan oluşur. Örneğin, new ile yarattığımız nesne önce Eden olarak isimlendirilen alana yerleşir. Eden dolduğunda küçük çöp toplayıcı (=Minor GC) çalışır.

Nesiller boyu Heap
Küçük çöp toplayıcı her çalıştığında, hayatta kalan nesneleri,  S0 yada S1 kodlu yaşam alanlarından birine taşınır. Her küçük çöp toplama sonunda Eden alanı tertemiz, S0 yada S1'den biri tertemiz, diğeri ise tüm canlı nesneleri barındırır. Bir nesne Eden'da doğar, sonrasında S0 ve S1 arasında pinpon topu gibi taşınıp durur. Bu taşımalarda nesnenin başından kaç küçük çöptoplayıcı geçtiği bir sayaçta saklanır. Belirli bir süre S0 ve S1 arasında taşınan nesne, bu sayaç belirli bir eşiği geçtiğinde, nesne emekli edilir ve Tenure alanına taşınır. Tenure alanı dolduğunda tam bir çöp toplama (=Full GC) gerçekleşir. 

Java'da nesnenin bir başlık kısmı bulunur. Bu başlık kısmında çeşitli bilgiler yer alır: sınıf bilgisinin olduğu Class sınıfı nesnesinin adresi, çeşitli bayraklar ve kilit adresi. Nesnenin bellekte kaç sekizli yer kapladığı özellikle çöp toplayıcının ne kadar sıklıkla çalıştığı ile ilgilidir. Nesnenin tartıda kaç sekizli çektiği, belleğe nasıl yerleştiğini öğrenebiliriz. Bu özellikle dağıtık cep sunucusu (=Distributed Cache Server) kullanıldığında, kümenin kaç sunucudan oluşacağı ve kapasite hesaplamasında önem kazanır. Nesnenin belleğe yerleşimi ve kaç sekizli yer kapladığını öğrenmek için OpenJDK içindeki bir projeden yararlanıyoruz: JOL (Java Object Layout). JOL kullanmak için bir Maven projesi yaratmanız ve pom.xml dosyasına aşağıdaki bağımlılığı eklemeniz gerekir:

<dependency>
   <groupId>org.openjdk.jol</groupId>
   <artifactId>jol-core</artifactId>
   <version>0.8</version>
</dependency>

Şimdi Java'daki temel tiplerin tamamını kullanarak tanımladığımız bir sınıfın (A sınıfı) üyelelerinin bellekteki dizilimine bir bakalım:

package com.example.jol.exercises;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise1 {
    public static void main(String[] args) {
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseClass(A.class).toPrintable());
    }
    
}

class A {
    byte b;
    short s;
    int i;
    long l;
    char c;
    boolean x;
    float f;
    double d;    
}

Uygulamayı önce 32 bitlik bir Java Sanal Makinasında (JSM) çalıştıralım:

# Running 32-bit HotSpot VM.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0     8           (object header)                           N/A
      8     8      long A.l                                       N/A
     16     8    double A.d                                       N/A
     24     4       int A.i                                       N/A
     28     4     float A.f                                       N/A
     32     2     short A.s                                       N/A
     34     2      char A.c                                       N/A
     36     1      byte A.b                                       N/A
     37     1   boolean A.x                                       N/A
     38     2           (loss due to the next object alignment)
Instance size: 40 bytes
Space losses: 0 bytes internal + 2 bytes external = 2 bytes total

32 bitlik JSM'de nesnenin başlığını 64 bit olarak ölçtük. Java'daki temel tiplerin bellekte kapladıkları alan JSM 32-bitlik ya da 64-bitlik olsun değişmez! A sınıfı nesnesi bellekte ham olarak 38 sekizlik yer kaplıyor. Nesneler belleğe, kopyalama ve taşıma işlemlerinin yüksek başarımla gerçekleşmesi için 64-bitin katları adreslere yerleşirilir. Nesnelerin belleğe kaç sekizlik olarak hizalanacağını kontrol eden bir JSM parametresi bulunuyor: ObjectAlignmentInBytes. Bunun değeri 64-bitlik işlemcilerde 8'dir, 32-bitlik işlemcilerde ise 4'dür. Nesnelerin belleğe hizalanması nedeni ile nesnenin sonunda kullanılmayan 2 sekizlik bir alan boş kaldı. JSM ayrıca öznitelikleri belleğe bizim kodda tanımladığımız sıradan farklı sırada yerleştirdi. JSM nesneyi belleğe olabilecek en tıkız (=compact) şekilde yerleştirdi! Bu JSM'nin en iyilemelerinden biridir ve varsayılan olarak açık geliyor: -XX:+CompactFields. Özniteliklerin belleğe yerleşiminin nasıl yapılacağını da kontrol edebiliriz. Bunun için JSM içinde bir parametre bulunuyor: FieldsAllocationStyle. Varsayılan değeri 1'dir ve bu değer için JSM önce temel tiplerden tanımlı öznitelikleri belleğe yerleştirir, daha sonra ise referans tipinden öznitelikleri belleğe yerleştirir. FieldsAllocationStyle=0 ise önce referans tipinden öznitelikleri belleğe yerleştirir, daha sonra temel tiplerden tanımlı öznitelikleri belleğe yerleştirir. FieldsAllocationStyle=2 ise öncelikli olarak hem temel sınıftan hem de sınıf içinde tanımlı olan referans tipinden öznitelikleri gruplayarak birlikte belleğe yerleştirir, daha sonra temel tiplerden tanımlı öznitelikleri belleğe yerleştirir.

Şimdi aynı uygulamayı 64-bitlik bir JSM'de çalıştıralım:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0    12           (object header)                           N/A
     12     4       int A.i                                       N/A
     16     8      long A.l                                       N/A
     24     8    double A.d                                       N/A
     32     4     float A.f                                       N/A
     36     2     short A.s                                       N/A
     38     2      char A.c                                       N/A
     40     1      byte A.b                                       N/A
     41     1   boolean A.x                                       N/A
     42     6           (loss due to the next object alignment)
Instance size: 48 bytes
Space losses: 0 bytes internal + 6 bytes external = 6 bytes total

İlk gözlemimiz 64-bitlik JSM'de nesne başlığının 12 sekizliğe yükseltilmiş olduğudur. JSM bir çok noktada en iyileme yapıyor. 64 bitlik bir makinada referans değişkenlerinin boylarıda 64 bite uzar. Ancak biz belleğin daha küçük bir kesimini kullandığımız için referans değişkenlerinin 64 bitlik uzunluğa sahip olmasına gerek yoktur. JSM, Heap boyu 32GB ulaşana kadar 64-bitlik işlemcide 32 bitlik adresler kullanarak Cep Bellek başarımını %15'e varan oranlarda iyileştiriyor. Bu en iyileme tekniğine Compressed Ordinary Object PointerS (OOPS) adı veriliyor ve bu özellikle varsayılan olarak açık geliyor. Şimdi bu özelliği kapttığımızda nesne başlığının ne kadar değiştiğine bir bakalım (-XX:-UseCompressedOops):

# Running 64-bit HotSpot VM.
# Objects are 8 bytes aligned.
# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0    16           (object header)                           N/A
     16     8      long A.l                                       N/A
     24     8    double A.d                                       N/A
     32     4       int A.i                                       N/A
     36     4     float A.f                                       N/A
     40     2     short A.s                                       N/A
     42     2      char A.c                                       N/A
     44     1      byte A.b                                       N/A
     45     1   boolean A.x                                       N/A
     46     2           (loss due to the next object alignment)
Instance size: 48 bytes
Space losses: 0 bytes internal + 2 bytes external = 2 bytes total

Nesne başlığı şimdi 16 sekizliğe yükseldi. 4 sekizlik bir artış var. 1 milyon A sınıfı nesnesi için 4 MB'lık bir kazanımımız var! Şimdilerde bellek ucuz ve kolay erişilebilir bir parça. Bu nedenle 4M'lık bir kazancın sizi pek heyecanlandırmadığını tahmin ediyorum. Farklı bir durum daha dikkatimizden kaçmadı: üyelerin belleğe yerleşimi değişti. Şimdi long ve double tipleri öne yerleştirdi. 16 sekizli, sekizin katı olduğu için önce en uzun tipleri yerleştirmeyle başladı. Bir önceki yerleşimde nesne başlığı 12 sekizli olduğu için ilk olarak sekizin katı adrese tamamlayacak tipi seçti: int (4 sekizli).

Şimdi daha karmaşık bir sınıf üzerinden incelememizi sürdürelim:

Person.java:

package com.example.domain;

import java.io.Serializable;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Person implements Serializable {
    private long id;
    private int identityNo;
    private String firstName;
    private String lastName;
    private int age;

    public Person() {
    }

    public long getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getIdentityNo() {
        return identityNo;
    }

    public void setIdentityNo(int identityNo) {
        this.identityNo = identityNo;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

   
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", identityCardNo=" + identityNo + ", firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + '}';
    }
    
}

Exercise2.java:

package com.example.jol.exercises;

import com.example.domain.Person;
import com.example.util.DataBuilder;
import java.lang.reflect.Field;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field value= String.class.getDeclaredField("value");
        value.setAccessible(true);
        Person person= DataBuilder.createRandomPerson();
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseInstance(person).toPrintable());
        System.out.println(ClassLayout.parseInstance(person.getFirstName()).toPrintable());
        System.out.println(ClassLayout.parseInstance(person.getLastName()).toPrintable());
        System.out.println(ClassLayout.parseInstance(value.get(person.getFirstName())).toPrintable());
        System.out.println(ClassLayout.parseInstance(value.get(person.getLastName())).toPrintable());
    }
    
}

Yukarıdaki uygulama çalıştırıldığında rasgele üretilen bir Person sınıfı nesnesinin bellekteki yerleşimini ekrana dökecektir:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.domain.Person object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           81 c0 00 20 (10000001 11000000 00000000 00100000) (536920193)
     12     4                int Person.identityNo                         1515124042
     16     8               long Person.id                                 1
     24     4                int Person.age                                54
     28     4   java.lang.String Person.firstName                          (object)
     32     4   java.lang.String Person.lastName                           (object)
     36     4                    (loss due to the next object alignment)
Instance size: 40 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4          (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4          (object header)                           da 02 00 20 (11011010 00000010 00000000 00100000) (536871642)
     12     4   char[] String.value                              [S, E, V, I, N, C]
     16     4      int String.hash                               0
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4          (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4          (object header)                           da 02 00 20 (11011010 00000010 00000000 00100000) (536871642)
     12     4   char[] String.value                              [K, U, T, A, Y]
     16     4      int String.hash                               0
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

[C object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           41 00 00 20 (01000001 00000000 00000000 00100000) (536870977)
     12     4        (object header)                           06 00 00 00 (00000110 00000000 00000000 00000000) (6)
     16    12   char [C.<elements>                             N/A
     28     4        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

[C object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           41 00 00 20 (01000001 00000000 00000000 00100000) (536870977)
     12     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
     16    10   char [C.<elements>                             N/A
     26     6        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 6 bytes external = 6 bytes total

Yukarıdaki çıktıdan, Person sınıfı nesnenin tüm üyeleri ile birlikte bellekte 40 + 24 + 24 + 32 + 32 = 152 sekizli yer kapladığını anlıyoruz. 

Dizilerin belleğe yerleşimini incelemekte fayda var:

package com.example.jol.exercises;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise3 {

    public static void main(String[] args) {
        int[] empty = new int[0];
        int[] one = new int[]{42};
        int[] numbers = new int[]{4, 8, 15, 16, 23, 42};
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseInstance(empty).toPrintable());
        System.out.println(ClassLayout.parseInstance(one).toPrintable());
        System.out.println(ClassLayout.parseInstance(numbers).toPrintable());
    }

}

Yukarıda verilen dizilerin belleğini incelemek amacıyla tasarlanmış örnek uygulama kodunu çalıştırdığımızda aşağıdaki çıktıyı elde ettik:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           6d 01 00 20 (01101101 00000001 00000000 00100000) (536871277)
     12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     0    int [I.<elements>                             N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           6d 01 00 20 (01101101 00000001 00000000 00100000) (536871277)
     12     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     16     4    int [I.<elements>                             N/A
     20     4        (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

[I object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           6d 01 00 20 (01101101 00000001 00000000 00100000) (536871277)
     12     4        (object header)                           06 00 00 00 (00000110 00000000 00000000 00000000) (6)
     16    24    int [I.<elements>                             N/A
Instance size: 40 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

İçi boş olan, sıfır elemanlı bir dizi bellekte 16 sekizli yer kaplıyor: 12 sekizli nesnenin başlığı ve 4 sekizli ise dizinin eleman sayısını saklamak için. Sıfır elemanlı, içi boş bir dizi için epey maliyetli bir gösterim! Tek elemanlı bir dizi ise 24 sekizlik alan kullanılıyor: 12 sekizli nesnenin başlığı, 4 sekizli dizinin eleman sayısı, 4 sekizli dizinin biricik elemanı için ve 4 sekizli ise hizalama amacıyla kullanılıyor. Tek bir tamsayı saklamak için hala çok maliyetli! 6 elemanlı bir dizi için ise 40 sekizli alana ihtiyaç var: 12 sekizli nesnenin başlığı, 4 sekizli dizinin eleman sayısı, 24 sekizli dizinin 6 adet elemanı için kullanılıyor.

Şimdi daha karmaşık bir alan sınıfından çok sayıda nesne yaratalım ve toplam bellek kullanımını raporlamaya çalışalım. Önce alan sınıflarına bir bakalım:

ListElement.java:

package com.example.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 *
 */
public class ListElement implements Serializable {
    private Person person;
    private JobInfo jobInfo;
    private final List<Phone> phones;
    private final List<String> addresses;
    private final List<ProgrammingLanguage> programmingLanguages;
    private final List<String> emails;
    
    {
        phones= new ArrayList<>();
        addresses= new ArrayList<>();
        programmingLanguages= new ArrayList<>();
        emails= new ArrayList<>();
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
    
    public JobInfo getJobInfo() {
        return jobInfo;
    }

    public void setJobInfo(JobInfo jobInfo) {
        this.jobInfo = jobInfo;
    }

    public List<Phone> getPhones() {
        return phones;
    }
    
    public Phone getPhone(int index) {
        return phones.get(index);
    }
    
    public void addPhone(Phone phone) {
        this.phones.add(phone);
    }

    public void addPhone(int index,Phone phone) {
        this.phones.add(index,phone);
    }

    public String getAdress(int index) {
        return addresses.get(index);
    }
    
    public List<String> getAddresses() {
        return addresses;
    }

    public void addAdress(String address) {
        this.addresses.add(address);
    }

    public void addAdress(int index,String address) {
        this.addresses.add(index,address);
    }

    public List<ProgrammingLanguage> getProgrammingLanguages() {
        return programmingLanguages;
    }

    public ProgrammingLanguage getProgrammingLanguage(int index) {
        return programmingLanguages.get(index);
    }
    
    public void addProgrammingLanguage(ProgrammingLanguage programmingLanguage) {
        this.programmingLanguages.add(programmingLanguage);
    }

    public void addProgrammingLanguage(int index,ProgrammingLanguage programmingLanguage) {
        this.programmingLanguages.add(index,programmingLanguage);
    }

    public List<String> getEmails() {
        return emails;
    }

    public String getEmail(int index) {
        return emails.get(index);
    }

    public void addEmail(String email) {
        this.emails.add(email);
    }

    public void addEmail(int index,String email) {
        this.emails.add(index,email);
    }
   
}

JobInfo.java:

package com.example.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 *
 */
public class JobInfo implements Serializable {

    private final String companyName;
    private final String companyAddress;
    private final List<String> jobTelNumbers;
    private final List<String> jobFaxNumbers;

    {
        jobTelNumbers = new ArrayList<>();
        jobFaxNumbers = new ArrayList<>();
    }

    public JobInfo(String companyName, String companyAddress) {
        this.companyName = companyName;
        this.companyAddress = companyAddress;
    }

    public String getCompanyName() {
        return companyName;
    }

    public String getCompanyAddress() {
        return companyAddress;
    }

    public List<String> getJobTelNumbers() {
        return jobTelNumbers;
    }

    public List<String> getJobFaxNumbers() {
        return jobFaxNumbers;
    }

    public void setJobFaxNumber(int index, String faxNumber) {
        jobFaxNumbers.add(index, faxNumber);
    }

    public void setJobFaxNumber(String faxNumber) {
        jobFaxNumbers.add(faxNumber);
    }

    public void setJobTelNumber(int index, String jobTelNumber) {
        jobTelNumbers.add(index, jobTelNumber);
    }

    public void setJobTelNumber(String jobTelNumber) {
        jobTelNumbers.add(jobTelNumber);
    }
    
}

Phone.java:

package com.example.domain;

import java.io.Serializable;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 *
 */
public class Phone implements Serializable {

    private String homePhoneNumber;
    private String gsmPhoneNumber;

    public Phone() {
    }

    public Phone(String homePhoneNumber, String gsmPhoneNumber) {
        this.homePhoneNumber = homePhoneNumber;
        this.gsmPhoneNumber = gsmPhoneNumber;
    }

    public String getHomePhoneNumber() {
        return homePhoneNumber;
    }

    public void setHomePhoneNumber(String homePhoneNumber) {
        this.homePhoneNumber = homePhoneNumber;
    }

    public String getGsmPhoneNumber() {
        return gsmPhoneNumber;
    }

    public void setGsmPhoneNumber(String gsmPhoneNumber) {
        this.gsmPhoneNumber = gsmPhoneNumber;
    }

}

ProgrammingLanguage.java:

package com.example.domain;

import java.io.Serializable;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 *
 */
public class ProgrammingLanguage implements Serializable {
    private String name;
    private int level;
    private double examNote;

    public ProgrammingLanguage() {
    }

    public ProgrammingLanguage(String name, int level, double examNote) {
        this.name = name;
        this.level = level;
        this.examNote = examNote;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public double getExamNote() {
        return examNote;
    }

    public void setExamNote(double examNote) {
        this.examNote = examNote;
    }

}

Şimdi ListElement sınıfından 10.000 tane rasgele nesne yaratalım ve bellekte ne kadar yer kapladığına bir bakalım:

package com.example.jol.exercises;

import com.example.domain.ListElement;
import com.example.util.DataBuilder;
import java.util.List;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.openjdk.jol.info.GraphLayout;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise3 {

    public static void main(String[] args) {
        IntFunction<? extends ListElement> int2ListElement = i -> DataBuilder.createRandomListElement();
        List<ListElement> list = IntStream.range(0, 10_000)
                .mapToObj(int2ListElement)
                .collect(Collectors.toList());
        System.out.println(GraphLayout.parseInstance(list).toFootprint());
    }

}

Uygulamayı çalıştırdığımızda ekran çıktısı aşağıdaki gibi gerçekleşiyor:

java.util.ArrayList@5fd0d5aed footprint:
     COUNT       AVG       SUM   DESCRIPTION
    141491        61   8755528   [C
     60001        56   3416232   [Ljava.lang.Object;
     10000        32    320000   com.example.domain.JobInfo
     10000        40    400000   com.example.domain.ListElement
     10000        40    400000   com.example.domain.Person
     20000        24    480000   com.example.domain.Phone
     30000        32    960000   com.example.domain.ProgrammingLanguage
    141491        24   3395784   java.lang.String
     60001        24   1440024   java.util.ArrayList
    482984            19567568   (total)

Yukarıdaki çıktıya göre 141491 adet char tipinde dizi yaratılmış, bu dizilerin ortalama uzunluğu 61 ve toplam boyu ise 8755528  olarak gerçekleşmiş. Beklediğimiz gibi 10.000 adet ListElement sınıfından nesne yaratılmış, her biri 40 sekizlik boyutunda olduğundan toplam olarak bellekte 400.000 sekizli yer kaplamış. Ancak ListElement sınıfının JobInfo, Person, Phone, ProgrammingLanguage, String tipleri ile bire-bir ve bire-çoklu türünden içerme ilişkileri bulunuyor. Dolayısı ile listede içerme ilişkisi de dahil edildiğinde toplam 482.984 adet nesne saklanıyor ve bu nesneler toplamda bellekte 19.567.568 sekizli yer kaplıyor.

Şu ana kadar incelememizi hep kaynak kodu elimizde olan uygulamalar için gerçekleştirdik. Şimdi ise diğer çözümlemelerimizden farklı olarak Heap yığını (=Heap dump) alınmış bir uygulama için farklı JSM modellerinde bellek yerleşim başarımının nasıl değiştiğini inceleyeceğiz:

package com.example.jol.exercises;
import java.io.File;
import java.io.IOException;
import static java.lang.System.out;
import org.openjdk.jol.datamodel.DataModel;
import org.openjdk.jol.datamodel.X86_32_DataModel;
import org.openjdk.jol.datamodel.X86_64_COOPS_DataModel;
import org.openjdk.jol.datamodel.X86_64_DataModel;
import org.openjdk.jol.heap.HeapDumpException;
import org.openjdk.jol.heap.HeapDumpReader;
import org.openjdk.jol.info.ClassData;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.layouters.HotSpotLayouter;
import org.openjdk.jol.layouters.Layouter;
import org.openjdk.jol.layouters.RawLayouter;
import org.openjdk.jol.util.Multiset;

public class Exercise5 {
    public static void main(String[] args) throws IOException, HeapDumpException {
        
        String path = args[0];

        out.println("Heap Dump: " + path);
        out.println("Estimated heap consumed, bytes:");

        HeapDumpReader reader = new HeapDumpReader(new File(path));
        Multiset<ClassData> data = reader.parse();

        for (DataModel model : new DataModel[]{new X86_32_DataModel(), new X86_64_DataModel(), new X86_64_COOPS_DataModel(), new X86_64_COOPS_DataModel(16)}) {

            Layouter l = new RawLayouter(model);
            long rawData = process(data, l);
            out.printf("%11s %,15d: %s%n", "", rawData, l);

            l = new HotSpotLayouter(model);
            long hsBase = process(data, l);
            out.printf("%11s %,15d: %s%n", "", hsBase, l);

            final boolean[] BOOLS = {false, true};

            for (boolean hierarchyGaps : BOOLS) {
                for (boolean superClassGaps : BOOLS) {
                    for (boolean autoAlign : BOOLS) {
                        for (boolean compactFields : BOOLS) {
                            for (int fieldAllocationStyle : new int[]{0, 1, 2}) {
                                l = new HotSpotLayouter(model, hierarchyGaps, superClassGaps, autoAlign, compactFields, fieldAllocationStyle);
                                long s = process(data, l);
                                out.printf("%10.3f%% %,15d: %s%n", (s - hsBase) * 100.0 / hsBase, s, l);
                            }
                        }
                    }
                }
            }
            out.println();
        }
    }

    static long process(Multiset<ClassData> data, Layouter layouter) {
        long totalFootprint = 0;
        for (ClassData cd : data.keys()) {
            ClassLayout layout = layouter.layout(cd);
            totalFootprint += layout.instanceSize() * data.count(cd);
        }
        return totalFootprint;
    }    
}

Yukarıdaki uygulamayı Exercise3 ile verilen uygulamanın Heap yığını (Heap dump) ile çalıştırıldığında aşağıdaki ekran çıktısı oluşuyor:

Heap Dump: c:/tmp/exercise3.hprof
Estimated heap consumed, bytes:
                160,943,452: Raw data (X32 model, 8-byte aligned)
                168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, compact fields, field allocation style: 1)
     1.427%     170,571,072: VM Layout Simulation (X32 model, 8-byte aligned, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, field allocation style: 2)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, compact fields, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, compact fields, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, compact fields, field allocation style: 2)
     1.182%     170,158,964: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, field allocation style: 2)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, compact fields, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, compact fields, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, autoalign, compact fields, field allocation style: 2)
     1.427%     170,571,072: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, field allocation style: 2)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, compact fields, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, compact fields, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, compact fields, field allocation style: 2)
     1.182%     170,158,964: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, field allocation style: 2)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 2)
     1.427%     170,571,072: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, field allocation style: 2)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 2)
     1.182%     170,158,964: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 2)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 2)
     1.427%     170,571,072: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 2)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 0)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 1)
     0.000%     168,171,040: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 2)
     1.182%     170,158,964: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 2)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 0)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 1)
    -0.245%     167,758,932: VM Layout Simulation (X32 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 2)

                239,746,052: Raw data (X64 model, 8-byte aligned)
                256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, compact fields, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, compact fields, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, compact fields, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, compact fields, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, compact fields, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, compact fields, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, autoalign, compact fields, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, compact fields, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, compact fields, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, compact fields, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 2)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 0)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 1)
     0.000%     256,200,936: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 2)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 0)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 1)
    -0.002%     256,196,168: VM Layout Simulation (X64 model, 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 2)

                180,227,628: Raw data (X64 model (compressed oops), 8-byte aligned)
                195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, compact fields, field allocation style: 1)
     0.000%     195,574,736: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, field allocation style: 0)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, field allocation style: 1)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, field allocation style: 2)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, compact fields, field allocation style: 0)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, compact fields, field allocation style: 1)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, compact fields, field allocation style: 2)
    -4.722%     186,339,900: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, field allocation style: 0)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, field allocation style: 1)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, field allocation style: 2)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, compact fields, field allocation style: 0)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, compact fields, field allocation style: 1)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, autoalign, compact fields, field allocation style: 2)
     0.000%     195,574,736: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, field allocation style: 0)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, field allocation style: 1)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, field allocation style: 2)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, compact fields, field allocation style: 0)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, compact fields, field allocation style: 1)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, compact fields, field allocation style: 2)
    -4.722%     186,339,900: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, field allocation style: 0)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, field allocation style: 1)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, field allocation style: 2)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 0)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 1)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, super gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     195,574,736: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, field allocation style: 0)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, field allocation style: 1)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, field allocation style: 2)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 0)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 1)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, compact fields, field allocation style: 2)
    -4.722%     186,339,900: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 0)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 1)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, field allocation style: 2)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 0)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 1)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     195,574,736: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 0)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 1)
     0.000%     195,575,088: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, field allocation style: 2)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 0)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 1)
     0.000%     195,574,560: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 2)
    -4.722%     186,339,900: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 0)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 1)
    -4.722%     186,340,252: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 2)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 0)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 1)
    -4.722%     186,339,724: VM Layout Simulation (X64 model (compressed oops), 8-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 2)

                180,227,628: Raw data (X64 model (compressed oops), 16-byte aligned)
                226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, compact fields, field allocation style: 1)
     0.000%     226,060,048: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, field allocation style: 0)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, field allocation style: 1)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, field allocation style: 2)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, compact fields, field allocation style: 0)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, compact fields, field allocation style: 1)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, compact fields, field allocation style: 2)
   -12.607%     197,560,756: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, field allocation style: 0)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, field allocation style: 1)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, field allocation style: 2)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, compact fields, field allocation style: 0)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, compact fields, field allocation style: 1)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, autoalign, compact fields, field allocation style: 2)
     0.000%     226,060,048: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, field allocation style: 0)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, field allocation style: 1)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, field allocation style: 2)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, compact fields, field allocation style: 0)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, compact fields, field allocation style: 1)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, compact fields, field allocation style: 2)
   -12.607%     197,560,756: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, field allocation style: 0)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, field allocation style: 1)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, field allocation style: 2)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, compact fields, field allocation style: 0)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, compact fields, field allocation style: 1)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, super gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     226,060,048: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, field allocation style: 0)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, field allocation style: 1)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, field allocation style: 2)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, compact fields, field allocation style: 0)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, compact fields, field allocation style: 1)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, compact fields, field allocation style: 2)
   -12.607%     197,560,756: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, field allocation style: 0)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, field allocation style: 1)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, field allocation style: 2)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 0)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 1)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, autoalign, compact fields, field allocation style: 2)
     0.000%     226,060,048: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, field allocation style: 0)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, field allocation style: 1)
     0.000%     226,060,064: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, field allocation style: 2)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 0)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 1)
     0.000%     226,060,016: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, compact fields, field allocation style: 2)
   -12.607%     197,560,756: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 0)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 1)
   -12.607%     197,561,108: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, field allocation style: 2)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 0)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 1)
   -12.607%     197,560,580: VM Layout Simulation (X64 model (compressed oops), 16-byte aligned, hierarchy gaps, super gaps, autoalign, compact fields, field allocation style: 2)

Bu çıktıdan uygulamanın bellekte kapladığı alanın, diğer bir deyişle ayak izinin JSM parametreleri ile değişimini izleyebilirsiniz. Elinizdeki uygulama için uygulamanın ayak izini iyileştirecek JSM parametre kümesine bu çıktıdan ulaşabilirsiniz. Yukarıdaki çıktıyı daha rahat okuyabilmeniz için çıktıdaki verileri aşağıda tablo formatında paylaşıyorum:

ModelAlignment SizeCompressed OopsAutoalignSuper gapsHierarchy gapsCompact fieldsField allocation styleSizeEfficiency
328FALSEFALSEFALSEFALSEFALSEraw160,943,452
328FALSEFALSEFALSEFALSETRUE1168,171,040
328FALSEFALSEFALSEFALSEFALSE0170,571,0721.43%
328FALSEFALSEFALSEFALSEFALSE1168,171,0400.00%
328FALSEFALSEFALSEFALSEFALSE2168,171,0400.00%
328FALSEFALSEFALSEFALSETRUE0168,171,0400.00%
328FALSEFALSEFALSEFALSETRUE1168,171,0400.00%
328FALSEFALSEFALSEFALSETRUE2168,171,0400.00%
328FALSETRUEFALSEFALSEFALSE0170,158,9641.18%
328FALSETRUEFALSEFALSEFALSE1167,758,932-0.25%
328FALSETRUEFALSEFALSEFALSE2167,758,932-0.25%
328FALSETRUEFALSEFALSETRUE0167,758,932-0.25%
328FALSETRUEFALSEFALSETRUE1167,758,932-0.25%
328FALSETRUEFALSEFALSETRUE2167,758,932-0.25%
328FALSEFALSETRUEFALSEFALSE0170,571,0721.43%
328FALSEFALSETRUEFALSEFALSE1168,171,0400.00%
328FALSEFALSETRUEFALSEFALSE2168,171,0400.00%
328FALSEFALSETRUEFALSETRUE0168,171,0400.00%
328FALSEFALSETRUEFALSETRUE1168,171,0400.00%
328FALSEFALSETRUEFALSETRUE2168,171,0400.00%
328FALSETRUETRUEFALSEFALSE0170,158,9641.18%
328FALSETRUETRUEFALSEFALSE1167,758,932-0.25%
328FALSETRUETRUEFALSEFALSE2167,758,932-0.25%
328FALSETRUETRUEFALSETRUE0167,758,932-0.25%
328FALSETRUETRUEFALSETRUE1167,758,932-0.25%
328FALSETRUETRUEFALSETRUE2167,758,932-0.25%
328FALSEFALSEFALSETRUEFALSE0170,571,0721.43%
328FALSEFALSEFALSETRUEFALSE1168,171,0400.00%
328FALSEFALSEFALSETRUEFALSE2168,171,0400.00%
328FALSEFALSEFALSETRUETRUE0168,171,0400.00%
328FALSEFALSEFALSETRUETRUE1168,171,0400.00%
328FALSEFALSEFALSETRUETRUE2168,171,0400.00%
328FALSETRUEFALSETRUEFALSE0170,158,9641.18%
328FALSETRUEFALSETRUEFALSE1167,758,932-0.25%
328FALSETRUEFALSETRUEFALSE2167,758,932-0.25%
328FALSETRUEFALSETRUETRUE0167,758,932-0.25%
328FALSETRUEFALSETRUETRUE1167,758,932-0.25%
328FALSETRUEFALSETRUETRUE2167,758,932-0.25%
328FALSEFALSETRUETRUEFALSE0170,571,0721.43%
328FALSEFALSETRUETRUEFALSE1168,171,0400.00%
328FALSEFALSETRUETRUEFALSE2168,171,0400.00%
328FALSEFALSETRUETRUETRUE0168,171,0400.00%
328FALSEFALSETRUETRUETRUE1168,171,0400.00%
328FALSEFALSETRUETRUETRUE2168,171,0400.00%
328FALSETRUETRUETRUEFALSE0170,158,9641.18%
328FALSETRUETRUETRUEFALSE1167,758,932-0.25%
328FALSETRUETRUETRUEFALSE2167,758,932-0.25%
328FALSETRUETRUETRUETRUE0167,758,932-0.25%
328FALSETRUETRUETRUETRUE1167,758,932-0.25%
328FALSETRUETRUETRUETRUE2167,758,932-0.25%
648FALSEFALSEFALSEFALSEFALSE1239,746,052
648FALSEFALSEFALSEFALSETRUE1256,200,936
648FALSEFALSEFALSEFALSEFALSE0256,200,9360.00%
648FALSEFALSEFALSEFALSEFALSE1256,200,9360.00%
648FALSEFALSEFALSEFALSEFALSE2256,200,9360.00%
648FALSEFALSEFALSEFALSETRUE0256,200,9360.00%
648FALSEFALSEFALSEFALSETRUE1256,200,9360.00%
648FALSEFALSEFALSEFALSETRUE2256,200,9360.00%
648FALSETRUEFALSEFALSEFALSE0256,196,1680.00%
648FALSETRUEFALSEFALSEFALSE1256,196,1680.00%
648FALSETRUEFALSEFALSEFALSE2256,196,1680.00%
648FALSETRUEFALSEFALSETRUE0256,196,1680.00%
648FALSETRUEFALSEFALSETRUE1256,196,1680.00%
648FALSETRUEFALSEFALSETRUE2256,196,1680.00%
648FALSEFALSETRUEFALSEFALSE0256,200,9360.00%
648FALSEFALSETRUEFALSEFALSE1256,200,9360.00%
648FALSEFALSETRUEFALSETRUE2256,200,9360.00%
648FALSEFALSETRUEFALSETRUE0256,200,9360.00%
648FALSEFALSETRUEFALSETRUE1256,200,9360.00%
648FALSEFALSETRUEFALSEFALSE2256,200,9360.00%
648FALSETRUETRUEFALSEFALSE0256,196,1680.00%
648FALSETRUETRUEFALSEFALSE1256,196,1680.00%
648FALSETRUETRUEFALSEFALSE2256,196,1680.00%
648FALSETRUETRUEFALSETRUE0256,196,1680.00%
648FALSETRUETRUEFALSETRUE1256,196,1680.00%
648FALSETRUETRUEFALSETRUE2256,196,1680.00%
648FALSEFALSEFALSETRUEFALSE0256,200,9360.00%
648FALSEFALSEFALSETRUEFALSE1256,200,9360.00%
648FALSEFALSEFALSETRUEFALSE2256,200,9360.00%
648FALSEFALSEFALSETRUETRUE0256,200,9360.00%
648FALSEFALSEFALSETRUETRUE1256,200,9360.00%
648FALSEFALSEFALSETRUETRUE2256,200,9360.00%
648FALSETRUEFALSETRUEFALSE0256,196,1680.00%
648FALSETRUEFALSETRUEFALSE1256,196,1680.00%
648FALSETRUEFALSETRUEFALSE2256,196,1680.00%
648FALSETRUEFALSETRUETRUE0256,196,1680.00%
648FALSETRUEFALSETRUETRUE1256,196,1680.00%
648FALSETRUEFALSETRUETRUE2256,196,1680.00%
648FALSEFALSETRUETRUEFALSE0256,200,9360.00%
648FALSEFALSETRUETRUEFALSE1256,200,9360.00%
648FALSEFALSETRUETRUEFALSE2256,200,9360.00%
648FALSEFALSETRUETRUETRUE0256,200,9360.00%
648FALSEFALSETRUETRUETRUE1256,200,9360.00%
648FALSEFALSETRUETRUETRUE2256,200,9360.00%
648FALSETRUETRUETRUEFALSE0256,196,1680.00%
648FALSETRUETRUETRUEFALSE1256,196,1680.00%
648FALSETRUETRUETRUEFALSE2256,196,1680.00%
648FALSETRUETRUETRUETRUE0256,196,1680.00%
648FALSETRUETRUETRUETRUE1256,196,1680.00%
648FALSETRUETRUETRUETRUE2256,196,1680.00%
8TRUEFALSEFALSEFALSEFALSEraw180,227,628
648TRUEFALSEFALSEFALSETRUE1195,574,560
648TRUEFALSEFALSEFALSEFALSE0195,574,7360.00%
648TRUEFALSEFALSEFALSEFALSE1195,575,0880.00%
648TRUEFALSEFALSEFALSEFALSE2195,575,0880.00%
648TRUEFALSEFALSEFALSETRUE0195,574,5600.00%
648TRUEFALSEFALSEFALSETRUE1195,574,5600.00%
648TRUEFALSEFALSEFALSETRUE2195,574,5600.00%
648TRUETRUEFALSEFALSEFALSE0186,339,900-4.72%
648TRUETRUEFALSEFALSEFALSE1186,340,252-4.72%
648TRUETRUEFALSEFALSEFALSE2186,340,252-4.72%
648TRUETRUEFALSEFALSETRUE0186,339,724-4.72%
648TRUETRUEFALSEFALSETRUE1186,339,724-4.72%
648TRUETRUEFALSEFALSETRUE2186,339,724-4.72%
648TRUEFALSETRUEFALSEFALSE0195,574,7360.00%
648TRUEFALSETRUEFALSEFALSE1195,575,0880.00%
648TRUEFALSETRUEFALSEFALSE2195,575,0880.00%
648TRUEFALSETRUEFALSETRUE0195,574,5600.00%
648TRUEFALSETRUEFALSETRUE1195,574,5600.00%
648TRUEFALSETRUEFALSETRUE2195,574,5600.00%
648TRUETRUETRUEFALSEFALSE0186,339,900-4.72%
648TRUETRUETRUEFALSEFALSE1186,340,252-4.72%
648TRUETRUETRUEFALSEFALSE2186,340,252-4.72%
648TRUETRUETRUEFALSETRUE0186,339,724-4.72%
648TRUETRUETRUEFALSETRUE1186,339,724-4.72%
648TRUETRUETRUEFALSETRUE2186,339,724-4.72%
648TRUEFALSEFALSETRUEFALSE0195,574,7360.00%
648TRUEFALSEFALSETRUEFALSE1195,575,0880.00%
648TRUEFALSEFALSETRUEFALSE2195,575,0880.00%
648TRUEFALSEFALSETRUETRUE0195,574,5600.00%
648TRUEFALSEFALSETRUETRUE1195,574,5600.00%
648TRUEFALSEFALSETRUETRUE2195,574,5600.00%
648TRUETRUEFALSETRUEFALSE0186,339,900-4.72%
648TRUETRUEFALSETRUEFALSE1186,340,252-4.72%
648TRUETRUEFALSETRUEFALSE2186,340,252-4.72%
648TRUETRUEFALSETRUETRUE0186,339,724-4.72%
648TRUETRUEFALSETRUETRUE1186,339,724-4.72%
648TRUETRUEFALSETRUETRUE2186,339,724-4.72%
648TRUEFALSETRUETRUEFALSE0195,574,7360.00%
648TRUEFALSETRUETRUEFALSE1195,575,0880.00%
648TRUEFALSETRUETRUEFALSE2195,575,0880.00%
648TRUEFALSETRUETRUETRUE0195,574,5600.00%
648TRUEFALSETRUETRUETRUE1195,574,5600.00%
648TRUEFALSETRUETRUETRUE2195,574,5600.00%
648TRUETRUETRUETRUEFALSE0186,339,900-4.72%
648TRUETRUETRUETRUEFALSE1186,340,252-4.72%
648TRUETRUETRUETRUEFALSE2186,340,252-4.72%
648TRUETRUETRUETRUETRUE0186,339,724-4.72%
648TRUETRUETRUETRUETRUE1186,339,724-4.72%
648TRUETRUETRUETRUETRUE2186,339,724-4.72%
6416TRUEFALSEFALSEFALSEFALSEraw180,227,628
6416TRUEFALSEFALSEFALSETRUE1226,060,016
6416TRUEFALSEFALSEFALSEFALSE0226,060,0480.00%
6416TRUEFALSEFALSEFALSEFALSE1226,060,0640.00%
6416TRUEFALSEFALSEFALSEFALSE2226,060,0640.00%
6416TRUEFALSEFALSEFALSETRUE0226,060,0160.00%
6416TRUEFALSEFALSEFALSETRUE1226,060,0160.00%
6416TRUEFALSEFALSEFALSETRUE2226,060,0160.00%
6416TRUETRUEFALSEFALSEFALSE0197,560,756-12.61%
6416TRUETRUEFALSEFALSEFALSE1197,561,108-12.61%
6416TRUETRUEFALSEFALSEFALSE2197,561,108-12.61%
6416TRUETRUEFALSEFALSETRUE0197,560,580-12.61%
6416TRUETRUEFALSEFALSETRUE1197,560,580-12.61%
6416TRUETRUEFALSEFALSETRUE2197,560,580-12.61%
6416TRUEFALSETRUEFALSEFALSE0226,060,0480.00%
6416TRUEFALSETRUEFALSEFALSE1226,060,0640.00%
6416TRUEFALSETRUEFALSEFALSE2226,060,0640.00%
6416TRUEFALSETRUEFALSETRUE0226,060,0160.00%
6416TRUEFALSETRUEFALSETRUE1226,060,0160.00%
6416TRUEFALSETRUEFALSETRUE2226,060,0160.00%
6416TRUETRUETRUEFALSEFALSE0197,560,756-12.61%
6416TRUETRUETRUEFALSEFALSE1197,561,108-12.61%
6416TRUETRUETRUEFALSEFALSE2197,561,108-12.61%
6416TRUETRUETRUEFALSETRUE0197,560,580-12.61%
6416TRUETRUETRUEFALSETRUE1197,560,580-12.61%
6416TRUETRUETRUEFALSETRUE2197,560,580-12.61%
6416TRUEFALSEFALSETRUEFALSE0226,060,0480.00%
6416TRUEFALSEFALSETRUEFALSE1226,060,0640.00%
6416TRUEFALSEFALSETRUEFALSE2226,060,0640.00%
6416TRUEFALSEFALSETRUETRUE0226,060,0160.00%
6416TRUEFALSEFALSETRUETRUE1226,060,0160.00%
6416TRUEFALSEFALSETRUETRUE2226,060,0160.00%
6416TRUETRUEFALSETRUEFALSE0197,560,756-12.61%
6416TRUETRUEFALSETRUEFALSE1197,561,108-12.61%
6416TRUETRUEFALSETRUEFALSE2197,561,108-12.61%
6416TRUETRUEFALSETRUETRUE0197,560,580-12.61%
6416TRUETRUEFALSETRUETRUE1197,560,580-12.61%
6416TRUETRUEFALSETRUETRUE2197,560,580-12.61%
6416TRUEFALSETRUETRUEFALSE0226,060,0480.00%
6416TRUEFALSETRUETRUEFALSE1226,060,0640.00%
6416TRUEFALSETRUETRUEFALSE2226,060,0640.00%
6416TRUEFALSETRUETRUETRUE0226,060,0160.00%
6416TRUEFALSETRUETRUETRUE1226,060,0160.00%
6416TRUEFALSETRUETRUETRUE2226,060,0160.00%
6416TRUETRUETRUETRUEFALSE0197,560,756-12.61%
6416TRUETRUETRUETRUEFALSE1197,561,108-12.61%
6416TRUETRUETRUETRUEFALSE2197,561,108-12.61%
6416TRUETRUETRUETRUETRUE0197,560,580-12.61%
6416TRUETRUETRUETRUETRUE1197,560,580-12.61%
6416TRUETRUETRUETRUETRUE2197,560,580-12.61%
6416TRUETRUETRUETRUETRUE2197,560,580-12.61%

FieldsAllocationStyle

Bu bölümde JSM tarafından uygulanan farklı yerleşim taktiklerini çalışacağız. Önce incelememizde kullanacağımız örnek kodu inceleyelim:

package com.example.jol.exercises;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise5 {

    public static void main(String[] args) {
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseClass(A.class).toPrintable());
    }
    
}

class A extends D{
    byte b;
    short s;
    int i;
    long l;
    char c;
    boolean x;
    float f;
    double d;    
    B ref1;
    C ref2;
}

class B {
    short s;
    int i;
}

class C {
    double d;
    boolean b;
}

class D {
    double d;
    boolean b;
    E ref3;
}

class E {
    double d;
    boolean b;
}
  • FieldAllocationStyle=0
Bu yerleşim taktiğinde, önce referans tipinden öznitelikler belleğe yerleştirilir, daha sonra temel tiplerden tanımlı öznitelikler belleğe yerleştirilir. Yukarıda verilen uygulama -XX:FieldAllocationStyle=0 seçeneği ile çalıştırılırsa üyelerin belleğe yerleşimi aşağıdaki şekilde gerçekleşiyor:
# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE                          TYPE DESCRIPTION                               VALUE
      0    12                               (object header)                           N/A
     12     4   com.example.jol.exercises.E D.ref3                                    N/A
     16     8                        double D.d                                       N/A
     24     1                       boolean D.b                                       N/A
     25     3                               (alignment/padding gap)                  
     28     4   com.example.jol.exercises.B A.ref1                                    N/A
     32     4   com.example.jol.exercises.C A.ref2                                    N/A
     36     4                           int A.i                                       N/A
     40     8                          long A.l                                       N/A
     48     8                        double A.d                                       N/A
     56     4                         float A.f                                       N/A
     60     2                         short A.s                                       N/A
     62     2                          char A.c                                       N/A
     64     1                          byte A.b                                       N/A
     65     1                       boolean A.x                                       N/A
     66     6                               (loss due to the next object alignment)
Instance size: 72 bytes
Space losses: 3 bytes internal + 6 bytes external = 9 bytes total
Yukarıdaki çıktıdan da görüleceği gibi JSM önce temel sınıf olan D sınıfından gelen üyeleri belleğe yerleştirdi. Bunu yaparken ise önce referans tipinden değişken olan ref3 değişkenini belleğe yerleştirdi. Ardından temel tiplerden üyeler belleğe yerleştirildi. Devamında ise A sınıfından tanımlanan üyeler belleğe yerleştirildi. Yerleşimde yine öncelikli olarak referans tipinden öznitelikler olan ref1 ve ref2 değişkenleri yerleştirildi. Bu yerleşim taktiğinde bellek kullanımı 72 sekizli olarak gerçekleşti.
  • FieldAllocationStyle=1
Bu yerleşim taktiğinde, önce temel tiplerden öznitelikler belleğe yerleştirilir. Daha sonra referans tipinden öznitelikler belleğe yerleştirilir. Yukarıda verilen uygulama -XX:FieldAllocationStyle=1 seçeneği ile çalıştırılırsa üyelerin belleğe yerleşimi aşağıdaki şekilde gerçekleşiyor:
# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE                          TYPE DESCRIPTION                               VALUE
      0    12                               (object header)                           N/A
     12     1                       boolean D.b                                       N/A
     13     3                               (alignment/padding gap)                  
     16     8                        double D.d                                       N/A
     24     4   com.example.jol.exercises.E D.ref3                                    N/A
     28     4                           int A.i                                       N/A
     32     8                          long A.l                                       N/A
     40     8                        double A.d                                       N/A
     48     4                         float A.f                                       N/A
     52     2                         short A.s                                       N/A
     54     2                          char A.c                                       N/A
     56     1                          byte A.b                                       N/A
     57     1                       boolean A.x                                       N/A
     58     2                               (alignment/padding gap)                  
     60     4   com.example.jol.exercises.B A.ref1                                    N/A
     64     4   com.example.jol.exercises.C A.ref2                                    N/A
     68     4                               (loss due to the next object alignment)
Instance size: 72 bytes
Space losses: 5 bytes internal + 4 bytes external = 9 bytes total
Yukarıdaki çıktıdan da görüleceği gibi JSM temel sınıf olan D sınıfından gelen üyeler için yer ayrıldı. Bunu yaparken önce temel tiplerden üyeler ve daha sonra referans türünden üyeler (ref3) yerleştirildi. Ardından A sınıfından gelen üyeler belleğe yerleştirildi. Bu yerleşimde de yine önce temel tiplerden üyeler bellektekini yerini aldıktan sonra referans tipinden üyeler ref1 ve ref2 değişkenleri belleğe ardışıl olarak yerleştirildi. Bu yerleşim taktiğinde bellek kullanımı 72 sekizli olarak gerçekleşti.
  • FieldAllocationStyle=2
Bu yerleşim taktiğinde öncelikli olarak hem temel sınıftan hem de sınıf içinde tanımlı olan referans tipinden öznitelikleri gruplayarak birlikte belleğe yerleştirir, daha sonra temel tiplerden tanımlı öznitelikleri belleğe yerleştirir.Yukarıda verilen uygulama -XX:FieldAllocationStyle=2 seçeneği ile çalıştırılırsa üyelerin belleğe yerleşimi aşağıdaki şekilde gerçekleşiyor:
# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.A object internals:
 OFFSET  SIZE                          TYPE DESCRIPTION                               VALUE
      0    12                               (object header)                           N/A
     12     1                       boolean D.b                                       N/A
     13     3                               (alignment/padding gap)                  
     16     8                        double D.d                                       N/A
     24     4   com.example.jol.exercises.E D.ref3                                    N/A
     28     4   com.example.jol.exercises.B A.ref1                                    N/A
     32     4   com.example.jol.exercises.C A.ref2                                    N/A
     36     4                           int A.i                                       N/A
     40     8                          long A.l                                       N/A
     48     8                        double A.d                                       N/A
     56     4                         float A.f                                       N/A
     60     2                         short A.s                                       N/A
     62     2                          char A.c                                       N/A
     64     1                          byte A.b                                       N/A
     65     1                       boolean A.x                                       N/A
     66     6                               (loss due to the next object alignment)
Instance size: 72 bytes
Space losses: 3 bytes internal + 6 bytes external = 9 bytes total
Yukarıdaki çıktıdan da görüleceği gibi JSM temel sınıf olan D sınıfından ve ondan türetilen A sınıfından gelen referans tipinden üyeleri gruplayarak belleğe yerleştirdi. ref3, ref1 ve ref2 değişkenleri belleğe ardışıl olarak yerleştirildi. Bu yerleşim taktiğinde bellek kullanımı 72 sekizli olarak gerçekleşti.
Örneğimizde verilen sınıflar ve aralarındaki ilişkiler için her üç yerleşim taktiği aynı boyuta sahip yerleşimler üretti. Değişen sadece  (=internal) ve dış (=external) bölünmelerden  (=fragmentation) kaynaklı kayıplar oldu. İç bölünme kalıtım sınıfları arasındaki hizalamadan dolayı oluşurken, dış bölünme ise nesneler arasındaki hizalamadan dolayı gerçekleşir. Buna göre, nesnenin bellekte kapladığı alanı değiştirmeden, birinci taktik (FieldsAllocationStyle=0) ve üçüncü taktik (FieldsAllocationStyle=2için D sınıfına 3 sekizlik ve A sınıfına 6 sekizlik üye ekleyebilirken, ikinci taktik (FieldsAllocationStyle=1için ise D sınıfına 5 sekizlik ve A sınıfına 5 sekizlik üye ekleyebiliriz. Sonuç olarak FieldsAllocationStyle parametresi, sınıf seviyesinde seçilebilecek bir parametre olmaması, bütüncül bir parametre olması nedeni ile JSM başarımını akort etmek için kullanılamaz.

Genel olarak nesnenin bellekte kaç sekizli bir alan kaplayacağını daha çok JSM'nin kaç bitlik olduğu, nesnelerin belleğe kaç sekizlik olarak hizalandığı ve Compressed OOPS özelliğinin açık olup olmaması belirlemektedir. Bunu Heap yığını alınmış bir uygulama için farklı JSM modellerinde bellek yerleşim başarım incelemesinde görmek mümkündür. Burada başarımı en çok Compressed OOPS en iyilemesi belirliyor. Bu en iyileme varsayılan olarak açık geliyor ve 64-bitlik bir JSM'de en tıkız bellek yerleşimi 186,339,724 sekizli ile Compressed OOPS özelliği açıkken elde ediliyor. Bu özellik kapalı olduğunda ise en tıkız bellek yerleşimi 256,196,168 sekizli olarak gerçekleşiyor. Compressed OOPS özelliği açıldığında bu değer 186,339,724 sekizliye düşüyor. İyileşme 69,856,444 sekizli kadar ediyor. İyileşmenin yüzde karşılığı -27.27Bu incelemelerden çıkarılması gereken en önemli ders, bir nesnenin bellekte kaç sekizli yer kapladığının hesabının, nesnenin üyelerinin boylarını toplayarak yapılamayacağıdır! Nesnenin bellekte kaç sekizli yer kaplayacağı ve bellekteki yerleşimi bir çok parametreye bağlı olarak değişmektedir: 
  • JSM'nin markası: Hotspot, JRockit, J9, Zing, Zulu gibi. Nesnenin başlık kısmı bir JSM'den diğerine değişebilir.
  • JSM'nin kaç bit olduğu: 32-bit ya da 64-bit gibi. 32-bitlik JSM'de başlık kısmının ve referansın boyu küçüktür. 64-bitlik JSM'de başlık kısmının boyu artsa da ve referans değişkenlerinin boyu iki katına çıksa da yazıda yukarıda açıklanan Compressed OOPS özelliği sayesinde belirli Heap boyutlarına kadar referans değişkenleri daha kısa sekizliler olarak gösterilir ve bellek yerleşiminde yerden kazanılır.
  • Nesnelerin kaç sekizli olarak hizalandığı: ObjectAlignmentInBytes parametresi bunu belirler. İşlemci mimarisine bağlı olarak değişir. 64-bitlik Intel işlemciler için 8 sekizlidir.
  • Nesnelerin üyelerinin belleğe yerleştirilme taktiği: FieldsAllocationStyle ve CompactFields parametreleri ile kontrol edilmektedir. Bu parametreler nesnenin bellekteki boyundan daha çok yerleşimini kontrol etmektedir.

@Contended

Java geliştiricisi çoğu zaman uygulamanın üzerinde çalıştığı işlemcinin detayı ve nesnenin belleğe nasıl dizildiği ile ilgilenmez. Ancak eğer paralel programlama yapıyorsanız ve İplikler (=Threads) ile çalışıyorsanız, nesnenin belleğe nasıl dizildiği önemli olabilir. Paralel programlamada paylaşılan verilere erişimi mutlaka düzenlemeniz gerekir. Eğer veriler cep bellekte ise daha fazla dikkat etmeniz gerekir. İşlemci içindeki cep bellekler hiyerarşik olarak düzenlenmiştir. İşlemciye en yakın Cep Bellek L1 cebidir. Genellikle her çekirdeğin kendi cep belleği bulunur ve cep bellekteki verilerin tutarlılığı için cep bellek bir cep tutarlılık protokolü (=cache coherence protocol) uygular. Intel MESIF protokolünü uygularken, AMD MOESI protokolünü uygular. Java'da uygulama geliştirirken nesnelerin paylaşılan alanlarını volatile tanımlarız. Burada amaç bir iplik tarafından volatile tanımlı alan üzerinde yapılan değişikliklerin, diğer iplikler tarafından görünür olmasını sağlamaktır. Ancak bu noktada yanıltıcı paylaşım (=false sharing) olarak adlandırılan bir problem ortaya çıkar. Önce problemi anlamaya çalışalım. SharedClass tipinden bir nesnenin x ve y üyeleri iki farklı çekirdekte çalışan iki iplik (t1 ve t2) tarafından okunmak ve değiştirilmek amacıyla erişilmektedir. 

class SharedClass {
    int x;
    int y;
}

İpliklerden biri (t1x'i değiştirmeye çalışırken diğer iplik (t2) ise y'yi değiştirmeye çalışsın. Cep belleğine erişim birimi, cep satırı (=cache line) olarak adlandırılır. x ve y üyeleri cebin aynı satırında yer alır. Dolayısı ile t1 ipliği x'i değiştirdiğinde, cep tutarlık protokolü o cep satırını kirli olarak etiketler ve diğer cep ise cep satırını geçirsiz kılar. Bir sonraki okuma için t2 ipliği ana belleğe gitmek zorundadır. Bu durumda t2 ipliği okuma için beklemek zorundadır. Aynı durum t2 ipliğinin y'yi değiştirmesi durumunda t1 ipliği için geçerlidir. Her iki iplik de gerçekte ortak bir bellek gözüne erişmiyor olsalar da, biri birilerini bekletmek durumunda kalmaktadırlar. Bu durum uygulamanın başarımını düşürecektir, uygulama birim zamanda daha az iş çıkaracaktır.
Bu problemi çözmenin bir yolu, x ve y üyelerinin farklı cep satırlarında yer almalarını sağlamak olabilir. Cep satırı 64 sekizli olan bir işlemci için x ve y arasına hiç kullanılmayacak ancak x ve y üyelerinin farklı cep satırlarında olmalarını sağlayacak dolgu değişkenleri tanımlanabilir:

class SharedClass {
    int x;
    long p1; 
    long p2; 
    long p3; 
    long p4; 
    long p5; 
    long p6; 
    long p7; 
    long p8; 
    int y;
}

Yukarıdaki kod çalıştırıldığında bellekteki yerleşim aşağıdaki gibi gerçekleşmektedir:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.SharedClass object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0    12        (object header)                           N/A
     12     4    int SharedClass.x                             N/A
     16     8   long SharedClass.p1                            N/A
     24     8   long SharedClass.p2                            N/A
     32     8   long SharedClass.p3                            N/A
     40     8   long SharedClass.p4                            N/A
     48     8   long SharedClass.p5                            N/A
     56     8   long SharedClass.p6                            N/A
     64     8   long SharedClass.p7                            N/A
     72     8   long SharedClass.p8                            N/A
     80     4    int SharedClass.y                             N/A
     84     4        (loss due to the next object alignment)
Instance size: 88 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

Şimdi x ve y değişkenleri farklı cep satırlarına yerleşmiş gözüküyor. Ancak bu çözümün farklı JSM'ler için çalışacağının bir garantisi bulunmuyor. Daha önce çalıştığımız gibi farklı JSM'ler sınıfın bu üyelerini belleğe farklı sıralarda dizebilir. Üstelik JSM'nin sınıfa eklediğimiz ve uygulama içinde hiç kullanılmayan bu dolgu değişkenlerini fark etmesi uzun sürmeyecektir ve JSM bu hiç kullanılmayacak dolgu değişkenlerini belleğe yerleştirmeyebilir! 

Java 8'de bu problemi çözmek üzere @Contended notu geldi. Bu notu yanıltıcı paylaşım problemine neden olan alanlara düşüyoruz:

package com.example.jol.exercises;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;
import sun.misc.Contended;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class Exercise6 {

    public static void main(String[] args) {
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseClass(SharedClass.class).toPrintable());
    }
}

class SharedClass {
    @Contended("group1")
    int x;
    @Contended("group2")
    int y;
}

Yukarıdaki kod -XX:-RestrictContended parametresi ile çalıştırılırsa SharedClass sınıfı üyelerinin belleğe yerleşimi aşağıdaki gibi gerçekleşiyor:

# Running 64-bit HotSpot VM.
# Using compressed oop with 0-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.example.jol.exercises.SharedClass object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0    12        (object header)                           N/A
     12   128        (alignment/padding gap)                  
    140     4    int SharedClass.x                             N/A
    144   128        (alignment/padding gap)                  
    272     4    int SharedClass.y                             N/A
    276     4        (loss due to the next object alignment)
Instance size: 280 bytes
Space losses: 256 bytes internal + 4 bytes external = 260 bytes total

Şimdi Hotspot, x ve y arasına cep satırının iki katı büyüklüğünde bir dolgu yerleştirdi. Nesnenin bellekte kapladığı alan 260 sekizliğe yükseldi! Bu ödenen yüksek bedele karşılık yanıltıcı paylaşım problemini çözdük!