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
,myClass2
değ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 nesnesi
de oluşturulmaz.i referans değişkeninin göstereceği Integer nesnesi
de oluşturulmaz.h
,j
,myClass3
değ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 nesnesi
heapte depolanır. Aynı şekildej nesnesinin gösterdiği Integer nesnesi
heapte depolanır.a
,b
vemyClass
local değişken olduklarından stackte depolanır.b referans değişkeninin gösterdiği Double nesnesi
heapte depolanır.myClass referans değişkeninin gösterdiği MyClass nesnesi
heapte depolanır.age
,myDate
,name
değişkenleri instance variable olduklarından nesne ile birlikte heapte depolanır.myDate referans değişkeninin gösterdiği Date nesnesi
heapte 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
,str
sınıf değişkenleri native memorydeki metaspace alanında depolanır.str referans değişkeninin gösterdiği String nesnesi
heapte depolanır. (heap içinde string constant pool denilen alanda)param
local değişken olduğundan stackte depolanır.args
local 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)