ÖNEMLİ : Kendim için aldığım notlar. Umarım size de bir faydası olur. Kullanılan her bir makale referans olarak eklenmiştir.

Java'da Hafıza Modeli Serisi


  1. Java’da Hafıza Modeli 1 - İlkel Veri Tipleri(Primitive Types)
  2. Java’da Hafıza Modeli 2 - Nesneler
  3. Java’da Hafıza Modeli 3 - Nesneler
  4. Java’da Hafıza Modeli 4 - Kapsam(Scope)
  5. Java’da Hafıza Modeli 5 - Pass By Value / Pass By Reference
  6. Java’da Hafıza Modeli 6 - Java’da Statik ve Statik Olmayan Değişken ve Metotların Hafıza Yönetimi
  7. Java’da Hafıza Modeli 7 - String Interning Nedir, String Pool Nedir, == operatörü ve equals metodu Arasındaki Fark
  8. Java’da Hafıza Modeli 8 - Java’da Static Initializer nedir? - Java statik ilklendirici
  9. Java’da Hafıza Modeli 9 - Java’da Instance Initializer Nedir? - Java örnek ilklendirici
  10. Java’da Hafıza Modeli 10 - Java’da Neden BAZI durumlarda metot kullanmak yerine initializer’ı tercih ederiz?

Genel Bakış

Java programlama dili statik olarak yazılmıştır(statically-typed), yani tüm değişkenlerin kullanılmadan önce bildirilmesi gerekir. Bu da, değişkenin türünü ve adını belirtmeyi içerir.

1
2
3
4
5
int var = 1;
//Bir değişkenin veri türü içerebileceği değerleri ve üzerinde
//yapılabilecek işlemleri belirler. int'ye ek olarak, Java
//programlama dili diğer yedi ilkel veri türünü de destekler.
//Bunları aşağıda görebilirsiniz.

İlkel Türler ve Referans Türleri


Veri türleri iki gruba ayrılır:

  • İlkel veri türleri
  • İlkel olmayan veri türleri String, Arrays(diziler) ve Classes(Sınıflar)

Örnek kod, programınıza “var” adlı bir alanın var olduğunu, sayısal verileri tuttuğunu ve başlangıç ​​değeri “1” olduğunu söyler. Bir alan, ilkel veya referans türünde(yani ilkel olmayanlar) olabilir. Sekiz ilkel tip vardır: boolean , byte , char , short , long , float ve double‘dır. Bir referans türü, arabirimler(interfaces), diziler(arrays) ve enumerated türler dahil olmak üzere, doğrudan veya dolaylı bir java.lang.Object alt sınıfı olan herhangi bir şey olabilir.

Java’da tanımlanan bu sekiz ilkel veri tipi nesne olarak kabul edilmez ve doğrudan yığın(stack) üzerinde depolanırlar. Fakat nesneler, ilkel veri tiplerinin aksine daha kompleks veri tipleri olduğundan heap adı verilen özel bir alanda depolanırlar. Her ne kadar farklı hafıza birimleri olsa da heap de stack de bilgisayarın RAM'inde yer alır. Heap ve stack dışında da JVM tarafından ayrılan bölümler vardır. Yalnız bu makalenin konusu sadece bu ikisini içerdiği için diğerlerine girmeyeceğim.

Bu yazıdaki asıl amacım, java’da ilkel(primitive) tür ve ilkel olmayan türler olan nesne ve dizilerin hafızada nasıl oluştuğunu resmederek göstermeye çalışmaktır.

İlkel tür, dil tarafından önceden tanımlanır ve ayrılmış(reserved keyword) bir anahtar sözcükle adlandırılır. (Yani int, double, short gibi…) İlkel değerler sahip olduğu durumu diğer ilkel değerlerle paylaşmaz.

String interning

Yukarıda listelenen 8 ilkel veri türüne ek olarak, Java programlama dili de java.lang.String sınıfı aracılığıyla karakter dizileri için özel destek sağlar. Karakter dizginizi çift tırnak içine almak otomatik olarak yeni bir String nesnesi oluşturur; örneğin, String s = "bu bir dizedir";. Dize nesneleri değiştirilemez, yani oluşturulduktan sonra değerleri değiştirilemez. String sınıfı teknik olarak ilkel bir veri türü değildir, ancak dil tarafından kendisine verilen özel destek göz önüne alındığında, muhtemelen bunu böyle düşünme eğiliminde olacaksınız. String objelerinin çift tırnak içerisinde gösterilme şekli sayesinde gereksiz string kalabalığından da kurtulmuş oluruz.

Örneğin “hello” değerinde bir string oluşturulduktan sonra, tekrar benzer değeri tutan bir string objesini çift tırnak("") kullanarak oluşturmak istesek, java bu objenin daha önceden oluştuğunu bildiği ve alandan tasarruf sağlamak istediği için ilk oluşturulan “hello” objesini kullanır. Bu işleme “string interning” denir. Yalnız bu durum new anahtar kelimesini kullanarak oluşturulan String objeleri için geçerli değildir. new anahtar kelimesini kullanarak oluşturulan String objeleri heap hafıza alanında her defasında yeni obje oluşturmaya zorlar. Bu da basit text içeren string objeleri için ekonomik sayılmaz. String’in bu iki türlü kullanımından ötürü string objeleri primitive muamelesi görür. Ama özünde değildir. Bu arada String’in java heap memory alanında string pool adında özel bir alana sahip olduğu için onu başka blog yazılarında bahsedeceğim. Şimdilik böyle bir statüye sahip olduğunu bilmemiz yeterli olacaktır.

Aşağıdaki şekilde string interning olayının nasıl gerçekleştiğini görebilirsiniz. a1 ve a2 referansları, string çift tırnak kullanılarak oluşturulduğu için aynı objeyi işaret ederken, new anahtar kelimesi ile oluşturulan a3 referansı ise farklı bir string objesini işaret etmektedir.

1
2
3
String a1 = "hello";
String a2 = "hello";
String a3 = new String("hello");


Java string interning

Arkadaşlar dilerseniz string interning ile alakalı hazırladığım bu videoya da göz gezdirebilirsiniz. Bu videoda string interning‘in yanı sıra bu konuyla bağlantılı olduğunu düşündüğüm 2 konuyu daha ele aldım. Bakmanızı öneririm.

İlkel Veri Türleri İçin Hafıza Modeli

Dilerseniz bir örnekle başlayalım.

1
2
3
4
5
6
int deg1;
deg1 = 5;
int deg2;
deg2 = deg1;
deg1 = 12;  
System.out.println("deg1 = "+ deg1 + ", deg2 = "+ deg2);

Adım adım yukarıdaki kod bloğu nasıl çalışır, bunu resmetmeye çalışalım.


Java variable assignment(java değişken atama)

Bu kutuyu, hafızada primitive type(ilkel tür) için açılan boşluğu, yani alanı temsil ediyor gibi düşünebilirsiniz.

  • 1.satır: Bu ilk satır bir değişken tanımlama işlemidir. Aslında Java’ya, tamsayı(int) tipinde bir değeri saklamak için yeni bir alan istiyorum, diyorsunuz. Ve o alanı(space) deg1 etiketiyle etiketleyeceğinizi belirtiyorsunuz. Şimdi hafıza modelimizde bunu göz önünde canlandırabilmek için bir kutu çizeceğiz. Bu kutu değişkeni temsil etmem gereken alanı(space) işaret ediyor. Sonrasında bu değişkeni deg1 ismiyle etiketliyorum.


Java variable assignment(java değişken atama)

  • 2.satır: Kodun bir sonraki satırı ise atama komutudur(assignment statement). Burada da Java’ya şunu söylüyorsunuz. Java sağ tarafta bulunan değeri al(yani 5’i) ve sol tarafta bulunan değişkene(yani deg1 olana) yerleştir(yani atama yap). Hafıza modelimize geri dönecek olursak, 5 sayısını alıp kutunun içine yerleştiriyor gibi düşünebiliriz.


Java variable assignment(java değişken atama)

  • 3.satır: Bu satırda, birinci satırda olduğu gibi yeni bir değişken tanımlıyoruz. Bu değişkenin ismini de deg2 olarak etiketlediğimizi düşünelim. deg1 için yaptıklarımızı aynen bunun içinde yapacağız. Bir kutu oluşturacak ve bu kutuyu deg2 ismiyle etiketleyeceğiz.

    Etiketlemekten kastım, aslında bir isim vereceğiz demek istiyorum. İngilizce label karşılığı etiketlemek olduğu için tercih ettim.


Java variable assignment(java değişken atama)

  • 4.satır: Bu satır bir başka atama komutunun olduğu satırdır. Bir önceki atama işlemlerinden biraz daha farklı olduğunu görebilirsiniz. Çünkü işlemin sağ tarafında bulunan değer bir rakam değil, başka bir değişkendir. Burada bizden istenen, deg1 değişkeninin sahip olduğu değerin aynısını deg2 değişkenine de atamaktır. Bu durumu, deg1 kutusunun içindeki değerin aynısını deg2 kutusunun içine yapıştırarak hafıza modelimizde resmedebiliriz. Resimden de görüleceği üzere deg1 ve deg2 değişkenleri aynı değeri saklamaya başladı. Dikkat edilecek olursa, bu iki değişken de tamamen farklı ve hiçbir şekilde birbirlerine bağlı değiller. Sadece geçici olarak aynı değeri saklıyorlar.


Java variable assignment(java değişken atama)

  • 5.satır: Bu satırda bir başka atama komutu ile karşılaşıyoruz. Bu sefer deg1 değişkenine 12 değerini atamamız isteniyor. Yani hafıza modelimizde düşünecek olursak: 12 değerini al ve deg1 değişkeninin olduğu kutuya yerleştir. Yani bu, eski değerimiz olan 5’in yerini şimdi 12 alacak demektir. Dikkat ederseniz değişen sadece deg1 değişkeni!! deg2 değişkeni için yaptığımız bir işlem olmadı. Daha önce de belirttiğimiz üzere, bu iki değişken arasında aynı değeri tutmalarının dışında bir benzerlik ve bağlantı yok. Tesadüfen aynı değeri tutan iki değişken gibi düşünülebilir.

  • 6.satır: Şimdi ise son satırımız olan print komutunun olduğu yere geldik. Bu bölümde bizden istenen deg1 ve deg2 değerlerini ekrana yazdırmak olacaktır. Yani hafıza modelimize bakarak konuşacak olursak, komutun bize söylediği; her bir değişkenin sahip olduğu kutuların içindeki değerleri oku ve ekrana yazdır!!! gibi düşünülebilir. Haliyle çıktımız aşağıdaki gibi olacaktır.

1
deg1 = 12 , deg2 = 5

Sözlük

  • statically-typed: değişken tiplerinin açıkça bildirildiği ve derleme zamanında belirlendiği bir programlama dili karakteristiğidir. Bu, derleyicinin belirli bir değişkenin kendisinden istenen eylemleri gerçekleştirip gerçekleştiremeyeceğine karar vermesini sağlar.

Referanslar