Java Memory Yönetimi

Java Memory Yönetimi

2 Şubat 2016 0 Yazar: Cem Kefeli

En sıkıntılı konulardan birisidir bir uygulamayı geliştirirken ve de canlıya alınması sonrasında karışılaşılan memory problemleri. Eğer geliştirme aşamasında tecrübelerinizden de faydalanarak olası memory problemlerini öngörebilirseniz canlıya çıkış sonrası oluşabilecek problemleri azaltabilirsiniz. Ya da daha geliştime ve test aşamasında bir memory problemi ile karşılaşırsanız, ki genelde uygulama gerçek yük altında çalışmaya başladığında açığa çıkarlar, fix etme imkanınız olur ve şanlısınız demektir.

C/C++ ile uygulama geliştirdiyseniz bilirsiniz ki bellek yönetimini tamamen geliştiriciye bırakır. Geliştirici istediği adresteki istediği bellek gözüne kadar herşeye hakimdir. Örneğin işaretçiler yardımıyla bellek gözlerini dilediği gibi yönetebilirler. Bu durum iyi kodlanmış yazılımlar için daha optimal memory kullanımlarını birlikte getirir. Düşünsenize tasarladığınız yazılımın her bir byte seviyesinde her bir bellek gözüne hakimsiniz ve nerede ne var tamamen biliyorsunuz, işlerinizi ona göre planlıyorsunuz. Ama ya iyi kodlanmamış bir yazılım varsa elinizde? Belki de iyi bir uygulama geliştirici değilsinizdir… Bellek yönetiminin esnekliği yerini bir anda bir kaos ortamına bırakıverir. Belki erişmemeniz gereken, sizin olmayan bir bellek gözlerine erişirmişsiniz ve hata alırsınız. Belki de ayırdığınız bellek alanlarının dışına çıkarsınız çalışma anında ve de yine hata alırsınız…

Bununla birlikte eğer nesle yönelimli (Object Oriented Programming – OOP) bir yazılım dili kullanarak uygulama geliştiriyorsanız sevindirici haberler de vardır. OOP konsepti herşeyi birer nesne olarak ele almak istediği için, nesnelerin varlığından ve de yokluğundan haberdar olmak isterler. Nesneleri doğduğu andan öleceği ana kadar takip ederler. Nesne doğduğu anda ona bir yuvacık sunarlar. Biraz ergenleştiği zaman onu yuvacıktan alıp yeni bir yuvaya nakleder ki yeni doğanlara yer açılsın. Nihayetinde zaman gelip de nesnenin ömrü dolduğunda kalıcı olarak yuvayı bozarlar ve nesne de artık yok olur. Bu yuva ve yuvacıkları bellek bölümleri olarak düşünebilirsiniz. Yuvaların tahsisi konusunu yöneten bir birim de vardır tabiki ve örneğin java için bu işi üstenen Garbage Collector (GC)’dür. GC, neslerin ömrü boyunca bellek işlerinden sorumlu müdürlüktür. Yeri geldiğinde kullanılmayan nesneleri de temizleyerek ilgili belleğin tekrar kullanılabilmesi amacıyla geliştiricinin hizmetine sunar. Geliştirici bu konseptte bellek işleri ile ilgilenmez.

Java Memory Management
Java Memory Management

Yukarıdaki şekilde Java’nın hafıza alanını nasıl bölümleyerek yönettiğini gösteren bir ifade bulunuyor. Temel olarak Heap ve Non-Heap olmak üzere iki ana bölüm var diyebiliriz. Heap alanında geliştiricinin yazılımın yaşamı süresince oluşturduğu tüm değişkenler yer almaktadır. Örneğin geliştirici yeni bir nesne oluşturduğunda bu nesne heap alana atılır ve ömrünü de burada tamamlar. GC, nesneleri heap alanındaki değişik bölümler arasında belirli bir algoritmaya göre gezdirir. Nesne ilk doğduğunda heap içerisindeki ‘eden space‘ ismi verilen yere atılır ki yuvacık işte burasıdır. Eden alanda yer azalmaya başladığında buradaki nesleler geçici süreliğine ‘survivor space‘ ismi verilen alana nakledilirler. Burada geçireceği süre diğer nesnelerin de durumuna göre değişiklik gösterecektir. Nihayetinde nesne son durağı olan ‘old space‘ alana taşınır ki burası artık nihayi yuvadır. Nesne ömrünü tamamladığında artık old alandan da kaldırılır ve işgal ettiği bellek alanı geliştiricinin tekrar kullanması amacıyla temizlenir.

Even, old ve survivor alanların boyutları tamamen konfigüratiftir ve varsayılan değerleri haricinde değiştirilebilirler. Yukarıdaki şekilde gösterilmeyen ‘-XX:SurvivorRatio’ ise survivor alanın boyutunu belirlemek için kullanılmaktadır. Örneğin bu değer 8 seçilirse, survivor alan eden alanın 1/8’i olsun anlamına gelir. Yani 8 birim eden alana, 1 birim survivor (to) alana ve 1 birim de survivor (from) alanına tahsis edilir. NewSize ile belirtilen değer bu oranlara bölünerek her bir bölümün boyutu belirlenmektedir. 

Permanent alanda ise nesne tanımlamaları ve metadatalar bulunmaktadır. Kod base’i yüksek olan uygulamalar doğal olarak daha yüksek boyutlarda perm alanlara da ihtiyaç duyacaktır. Yine bu bölümlerin boyutları da tamamen konfigüratiftir ve varsayılan haricinde değerlerde ayarlanabilirler.