Heap Space vs Stack
Java'da primitif ve referans değişkeni olmak üzere 2 tip değişken vardır.
Primitif Değişkenler
Primitif değişkenler değerlerini kendi üzerlerinde taşırlar. Bunlar 8 tipten biri olabilir.
| Veri tipleri | Java dilinde karşılıkları |
|---|---|
| Tam sayılar | byte, short, int, long |
| Kesirli sayılar | float, double |
| Karakter | char |
| Mantıksal | boolean |
Referans Değişkeni
Referans değişkeni bir nesneyi işaret eder (C/C++ programcıları bunları C/C++'daki pointerlara benzetebilir). Referans değişkenlerine örnek olarak herhangi bir sınıf tipindeki değişkenleri verebiliriz. Örneğin: Date date, String str.
Primitif değişkenler ve referans değişkenleri şu durumlarda olabilirler.
- class variable : Sınıfa ait değişken,
- instance variable : Nesneye ait değişken,
- local variable : Metodun içinde tanımlanan değişken (metod parametreleri de dahil).
Veriler Nerede Saklanır?
- Tüm nesneler heap alanında depolanır. Örnek değişkenler(instance variables) de nesneye ait olduklarından heap alanında depolanır.
- Tüm local değişkenler yığın (stack) da depolanır.
-
Sınıf değişkenleri (yani static tanımlanmış değişkenler) Java 7'de heap bölgesi içinde yer alan PermGen (Permanent Generation) adı verilen özel bir alanda depolanıyor.
Java 8 ile birlikte PermGen alanı kaldırıldı. Oracle HotSpot JVM, artık sınıf metadatalarını Java Process Heap(Native Memory) alanında yer alan Metaspace alanında depoluyor.
Özetlersek static tanımlanmış değişkenler Java 8 de native memory içinde Metaspace alanında, Java 7'de heap bölgesi içerisinde yer alan PermGen alanında depolanıyor.
| Oracle HotSpot Heap Structure | JDK 1.8 Oracle HotSpot Heap Structure |
|---|---|
|
|
Analiz
Örnek bir kod üzerinden anlatmak gerekirse,
| import java.util.Date; | |
| public class Test { | |
| int g = 3; | |
| static int h = 10; | |
| Integer i = 12; | |
| static Integer j = 11; | |
| MyClass myClass2 = new MyClass(); | |
| static MyClass myClass3 = new MyClass(); | |
| public static void main(String args[]) { | |
| double a = 5.4; | |
| Double b = 18.0; | |
| MyClass myClass = new MyClass(); | |
| myClass.setName("fatih"); | |
| } | |
| } | |
| class MyClass { | |
| int age = 10; | |
| static int number = 15; | |
| Date myDate = new Date(); | |
| String name; | |
| static String str = "String Deneme"; | |
| public void setName(String param) { | |
| this.name = param; | |
| } | |
| } |
g,i,myClass2değişkenleri instance variable olduklarından bu değişkenler oluşturulmaz (programımızda hiç Test nesnesi oluşturmadık). Hiç bir yerde depolanmaz. Dolayısıyla initialization(ilk değer atamaları) da yapılmaz.myClass2 referans değişkeninin göstereceği MyClass nesneside oluşturulmaz.i referans değişkeninin göstereceği Integer nesneside oluşturulmaz.h,j,myClass3değişkenleri sınıf değişkeni olduklarından native memorydeki metaspace alanında depolanır (Java 8 için).myClass3 referans değişkeninin gösterdiği MyClass nesnesiheapte depolanır. Aynı şekildej nesnesinin gösterdiği Integer nesnesiheapte depolanır.a,bvemyClasslocal değişken olduklarından stackte depolanır.b referans değişkeninin gösterdiği Double nesnesiheapte depolanır.myClass referans değişkeninin gösterdiği MyClass nesnesiheapte depolanır.age,myDate,namedeğişkenleri instance variable olduklarından nesne ile birlikte heapte depolanır.myDate referans değişkeninin gösterdiği Date nesnesiheapte depolanır. Aynı şekilde name referans değişkeninin göstereceği nesne heapte depolanır (new ile oluşturulmadığından dolayı heap içinde string constant pool denilen alanda bulunur).number,strsınıf değişkenleri native memorydeki metaspace alanında depolanır.str referans değişkeninin gösterdiği String nesnesiheapte depolanır. (heap içinde string constant pool denilen alanda)paramlocal değişken olduğundan stackte depolanır.argslocal değişkeni stackte depolanır.- setName methoduna gönderilen argümanda
"fatih"bir nesne olduğundan heap alanında depolanır. (string constant pool denilen alanda)