Pure Java – 37 Garbage Collection

Merhaba Arkadaslar bu yazimda Java da Garbage Collection mekanizmasindan bahsedecegim.

Oncelikle Garbage Collection nedir sorusuna yanit arayalim , Garbage Collection memory/kaynak yonetiminin adidir. Bir bilgisayar programi calistiginda ister Java ister C, C++ veya farkli bir dil olsun memory(hafiza) kullanimi soz konusudur.  C gibi dillerde pointer kullanimi, calloc() , malloc() ve free() gibi fonksiyonlarla memory yonetimi yapilirken Java da bu memory yonetimi Garbage Collector tarafindan saglanmaktadir.

Garbage Collector, otomatik Garbage Collection mekanizmasi ile memory-leak(bellek aciklari/sizintilari)’lere engel olarak Java’nin Robust (dayanikli, guclu,direncli) ozelligini saglamaya yardimci olur.
Ayrica C gibi dillerde olan free() fonksiyonu yerine, Javada Garbage Collector bu isi uslendigi icin bir nevi pointer mekanizmasindan kurtulmamiza destek saglar. Bu da Java’nin Simple(Basit) ozelligini saglamaktadir.
Java’nin ozelliklerine dair Akin Kaldiroglu hocamizin yazisini ve ingilizce kaynak olarak ilgili kaynagi inceleyebilirsiniz;

http://www.javaturk.org/?p=48
http://web.cs.wpi.edu/~cs525e/s01/java/features.html

Bir Java programi calistiginda JVM(Java Virtual Machine) , Isletim Sisteminden, memory(hafiza) temin eder. Bu alana Java Heap Memory ya da kisaca heap deriz. Hatirlayacagimiz gibi Java da objeler ve instance variable’lar Heap’te mutlu mutlu yasarlar.

Garbage Collector calistiginda amaci Heap’te bulunan ve ulasilamayan(unreachable bir nevi death) objeleri Heapten silmektir ve bu alani yeni objeler icin hazirlamaktir.

Yazimin devaminda Garbage Collector yerine GC kisaltmasini kullanacagim. Peki aklimiza su soru gelmektedir GC’ler ne zaman nasil cagrilir ?
GC , JVM (Java Virtual Machine)’in kontrolu altindadir. Dolayisiyla GC’nin ne zaman calisacagi JVM’in kontrolundedir. Bir Java programindan , JVM’e GC’yi calistirmasi icin istekte bulunabiliriz fakat istegimizin kabul edilecegine dair bir garanti yoktur!

Java’da basit bir HelloWorld programi bile yazsak, yani bir main metodu kullansak en azindan bir Thread’in calismasina neden oluruz.Ilerleyen yazilarda Thread konusunu isleyecegiz , simdilik burada Thread’in alive veya dead oldugu duruma gore konusalim. Her Thread’in kendi bir yasam dongusu vardir(lifecycle) ve kendi Stack alani vardir.

Bir objeye, yasayan (alive) hic bir Thread ulasmiyorsa , bu obje GC tarafindan yok edilmeye uygundur. Bununla birlikte bir objeye hic bir canli(alive) thread ulasmamasina ragmen ve bu objenin silinmesi isleminin uygun olmasina ragmen bir nedenle bu silme islemi gerceklesmeyebilir. Bu nedenle burada da bir garanti yoktur!

Simdi de ornek kodlar yazalim ve objelerin hangi durumlarda garbage collection icin uygun oldugunu incelemeye calisalim;

Nulling a Reference(Referans degiskenine null atama islemi)
Bir objeye ulasabilen bir referans degiskeni yoksa, bu objeye ne olacaginin pek onemi yoktur. Yani bu durumda garbage collection icin uygun hale gelir.

public class GarbageTest {

	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer("Levent");
		System.out.println(sb);
		// StringBuffer objesi garbage collection icin uygun degil!

		sb = null;
		// Simdi ise garbage collection icin uygun hale gelir.
	}
}

Reassigning a Reference Variable( Referans degiskenine tekrar atama islemi)
Bir referans degiskeninin referansta bulundugu obje degistirilirse yani tekrar atama islemi yapilirsa ve bu objeye baska bir degisken tarafindan referansta bulunulmuyorsa , ilgili obje garbage collection icin uygun hale gelecektir.

public class GarbageTest2 {

	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer("levent");
		StringBuffer sb2 = new StringBuffer("erguder");

		System.out.println(sb);
		// bu noktada sb referans degiskeninin referans ettigi obje
		// garbage collection icin uygun degildir.

		sb = sb2;
		// bu noktada sb referans degiskeninin referans ettigi obje
		// garbage collection icin uygun hale gelmistir.
		// sb referans degiskenin tuttugu "levent" StringBuffer objesine baska
		// bir referans degiskeni referansta bulunmamaktadir.
	}
}

Su ornegimizi inceleyelim;

public class GarbageTest3 {

	public static void main(String[] args) {
		Date d = getDate();

		//bu adimda sb referans degiskeninin referansta bulundugu StringBuffer "levent" objesi
		//GC tarafindan silinmek icin uygun hale gelecektir. getDate() metodu calismis ve bitmistir.

		System.out.println(d);

		//bu adimda
		//d2 referans degiskeninin yasam alani getDate metodu sonlaninca bitmesine ragmen ilgili objeyi 
		//d referans degiskeni gosterecegi icin Date objesi GC tarafindan silinmek icin uygun durumda degildir.

	}

	public static Date getDate() {
		Date d2 = new Date();

		StringBuffer sb = new StringBuffer("levent");

		return d2;

		//metot tamamlandiginda sb referans degiskeninin referansta bulundugu
		// StringBuffer "levent" objesi garbage collection icin uygun hale gelecektir
		// cunku sb degiskeninin yasam alani(scope) getDate metodu ile sinirlidir.
		// bu metot sonlaninca sb referans degiskenin scope alani sonlanacaktir ve referansta bulundugu obje
		// GC tarafindan silinmeye uygun hale gelecektir.

		//bununla birlikte bu metot d2 referans degiskenini dondurmektedir,
		//main metodundaki d referans degiskeni ile d2 referans degiskeni ayni Date objesini gosterecektir.

	}
}

Aciklamalari kod uzerinde yapmaya calistim, kisacasi onemli olan ilgili adimda yasayan bir thread’ten bir referans degiskenin ilgili objeye ulasip ulasamadigidir.

Isolating a Reference
Bir baska durum ise “islands of isolation” durumudur. Kod uzerinde incelemeye devam edelim;

public class Island {

	Island i;

	public static void main(String[] args) {
		Island i2 = new Island();
		Island i3 = new Island();
		Island i4 = new Island();

		//3 tane Island turunde obje olusturduk

		i2.i = i3; // i2.i , i3 e referansta bulunur
		i3.i = i4; // i3.i , i4 e referansta bulunur
		i4.i = i2; // i4.i , i2 ye referansta bulunur

		i2=null;
		i3=null;
		i4=null;

		// i2, i3,i4 referans degiskenlerine null degeri atadik.

		//i2.i referans degiskeni yine i3 un referansta bulundugu Island objesine
		//i3.i referans degiskeni yine i4 un referansta bulundugu Island objesine
		//i4.i referans degiskeni yine i2 nin referansta bulundugu Island objesine referansta bulunmaktadir.
		//Fakat bunlar kendi aralarinda bir ada(Island) olustuduklari icin ve disariyla baglantilari olmadigi icin
		//Garbage Collector calistiginda bunun farkina varacak ve olusturulan bu 3 obje de silinmek icin uygun hale gelecektir.
	}

}

Forcing Garbage Collection
Aslinda Garbage Collection mekanizmasini “zorlayamayiz” yukarida belirtigim gibi program icerisinde JVM’e istekte bulunabiliriz ve mekanizmayi tetiklemeye calisabiliriz. JVM bizim istegimizi dikkate almak veya tum silinmek icin uygun olan objeleri silmek gibi bir garantisi yoktur!

Java’da bulunan Runtime sinifi araciligi ile (Runtime instance ile) JVM ile iletisim kurabiliriz ve Garbage Collection mekanizmasini calistirmasi icin istekte bulunabiliriz. Kucuk bir ornek yapalim bu ornegimizde 100bin Date objesi olusturalim;

import java.util.Date;

public class CheckMemory {

	public static void main(String[] args) {

		Runtime rt = Runtime.getRuntime(); 

		System.out.println("Total Memory:"+rt.totalMemory());
		System.out.println("Free Memory:"+rt.freeMemory());

		Date d=null;
		//Bu adimda cilginca Date objesi olusturalim 🙂
		for(int i=0; i<100000; i++){
			d= new Date();
			d=null;
		}
		//Deli gibi Date objesi olusturduk simdi freeMemory metodunu tekrar cagiralim
		System.out.println("After Free Memory:"+rt.freeMemory());

		//rt referans degiskeni ile JVM e garbage collector u calistirma isteginde bulunalim.
		rt.gc(); // ya da System.gc();
		System.out.println("After GC Free Memory:"+rt.freeMemory());
	}

	// Bendeki ornek cikti su sekilde, calistirdiginizda sizde farkli olacaktir
	// GC tum olusturalan objeleri silmeyi garanti etmedigi icin After GC Free Memory farkliliklar gosterebilir.

	//Total Memory:62390272
	//Free Memory:61717816
	//After Free Memory:59750560
	//After GC Free Memory:61803160

}

Aciklamalari kod icerisinde yapmaya calistim. Kisacagi gc() metodu ile JVM e istekte bulunuruz ve istegimizin dikkate alinmasinin veya sonuclarinin garantisi yoktur!

Yazimi burada sonlandiriyorum. Bu yazidan cikaracagimiz en onemli sonuc sudur ;
In Java , you cant trust Thread and GC , in life ; women.

Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
injavawetrust

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *