Çöp toplama yoluyla otomatik bellek yönetimi, ART sanal makinesine dayanan Android platformunun temel bir mekanizmasıdır. Google Android Documentation, 2026'ya göre, çöp toplayıcı, geliştiriciyi manuel bellek yönetiminden kurtarır ve artık referansı olmayan nesneleri otomatik olarak kaldırır. GC olmadan, her nesne tahsisi açıkça free veya delete çağrısı gerektirirdi ki bu, saniyede milyonlarca nesneyle Java ekosisteminde fiziksel olarak imkansızdır.
Önemli Noktalar
Garbage Collection (GC), program tarafından artık kullanılmayan nesnelerin kapladığı belleği algılama ve boşaltma işlemidir. Mobil geliştirme bağlamında, GC, ART sanal makinesi aracılığıyla Android platformunda ve standart Java Virtual Machine'de kullanılır.
Manuel bellek yönetimine sahip dillerin (C, C++) aksine, programcının açıkça free veya delete çağırması gerekirken, GC nesne yaşam döngüsünü izleme görevini tamamen üstlenir. Geliştirici, new operatörüyle yeni nesneler oluştururken, toplayıcı bir nesnenin ne zaman ulaşılamaz hale geldiğini — yani ona hiçbir aktif referans kalmadığını belirler.
GC verimliliğinin temel metrikleri duraklama süresi (pause time) ve iş hacmidir (throughput). Duraklama, toplama işlemi için uygulama yürütmesinin durdurulduğu süredir. Mobil ortamda, 8–16 milisaniyeden uzun duraklamalar, düşen kareler (jank) olarak fark edilir.
Google I/O 2019'a göre, Android 10'daki ART, tipik GC duraklamalarını 2–4 ms'ye düşürerek Android 4.4'teki Dalvik'e kıyasla %70 azalma sağladı. Bununla birlikte, uygunsuz bellek yönetimi — döngülerde sık nesne tahsisi, gereksiz geçici örnekler oluşturma — performans sorunlarının ana nedeni olmaya devam ediyor.
Java ve Android'deki tüm GC uygulamaları, duraklama süresi ve temizleme bütünlüğü arasında denge sağlamak için birleştirilen birkaç temel algoritmaya dayanır. Bu algoritmaları anlamak, GC dostu kod yazmak için gereklidir.
Mark-and-Sweep, iki aşamada çalışan en basit algoritmadır. Mark aşamasında, toplayıcı, kök referanslardan (root set) — yerel değişkenler, statik alanlar, iş parçacığı yığınları — başlayarak nesne grafiğini dolaşır. Ulaşılabilir her nesne canlı bayrağıyla işaretlenir. Sweep aşamasında, toplayıcı tüm yığını tarar ve işaretlenmemiş nesnelerin belleğini boşaltır.
Dezavantajı bellek parçalanmasıdır: Sweep'ten sonra boş alanlar dolu alanlarla dönüşümlü olarak sıralanır ve büyük nesnelerin tahsisini zorlaştırır. Mobil senaryolarda bu kritiktir çünkü yığın genellikle küçüktür (Android'de 64–512 MB).
Copying Collection, yığını iki yarı-uzaya (semi-spaces) böler. Aktif nesneler, boşluksuz olarak bir yarı-uzaydan diğerine sıkıştırılarak kopyalanır. Kopyalamadan sonra eski yarı-uzay tamamen boş ilan edilir. Algoritma, parçalanmayı tamamen ortadan kaldırır ancak iki kat daha fazla bellek gerektirir.
Mobil ortamlarda Copying Collection, istatistiksel olarak erken ölen genç nesnelerin (zayıf kuşak hipotezi) hızlı temizliği için kuşaksal toplayıcılar tarafından kullanılır.
Generational Collection, yığını kuşaklara ayırır: Young Generation (genç nesneler) ve Old Generation (birkaç koleksiyondan kurtulan yaşlı nesneler). Genç kuşağın toplanması (Minor GC) sık ve hızlı yapılır çünkü çoğu nesne genç yaşta ölür. Yaşlı kuşağın toplanması (Major GC veya Full GC) daha seyrek olur ancak daha uzun sürer.
// Kuşaksal GC gösterimi: genç nesneler hızla ölür
void processItems(List<Item> items) {
List<Result> results = new ArrayList<>(); // tüm metod boyunca yaşar
for (Item item : items) {
Result r = new Result(item.getValue()); // anında ölür
if (r.isValid()) {
process(r); // r çöp haline gelir
}
}
saveResults(results); // results Old Gen'e geçer
}
Bu örnekte, Result nesneleri bir döngü içinde oluşturulur ve hemen çöp haline gelir — bunlar Young GC için ideal adaylardır. results nesnesi daha uzun yaşar ve Old Generation'a geçer. Kuşak ayrımı, Minor GC'nin eski yığına dokunmadan genç nesneleri milisaniyeler içinde temizlemesine olanak tanır.
Android, Dalvik VM'den ART'ye (Android Runtime) evrildi ve GC uygulaması aralarındaki temel farklardan biridir. Android'deki GC mimarisini anlamak, gerçek cihazlarda duraklamaları en aza indiren kod yazmaya yardımcı olur.
| Özellik | Dalvik (4.4'e kadar) | ART (5.0+) |
|---|---|---|
| GC Türü | Concurrent Mark ile Mark-and-Sweep | Generational + Concurrent |
| Tipik duraklama | 10–30 ms | 2–4 ms |
| Sıkıştırma | Hayır (sadece parçalanma artar) | Evet (arka planda, uygulamayı durdurmadan) |
| AOT Derleme | JIT (Just-In-Time) | AOT + JIT (hibrit) |
Dalvik, eşzamanlı bir aşamayla Mark-and-Sweep kombinasyonunu kullandı. Concurrent Mark, nesne grafiği geçişi sırasında uygulamanın çalışmaya devam etmesine izin verirken, Sweep aşaması tüm iş parçacıklarının durdurulmasını gerektiriyordu (Stop-The-World). Az RAM'e sahip cihazlarda (512 MB — 1 GB), duraklamalar 30 ms'ye ulaştı ve arayüzde belirgin yavaşlamalara neden oldu. Ayrıca Dalvik yığını sıkıştırmadı, bu nedenle uzun süreli kullanımdan sonra parçalanma arttı ve yeterli toplam boş bellek olmasına rağmen büyük nesnelerin (örneğin, Bitmap) tahsisi OutOfMemoryError fırlatabiliyordu.
ART (Android Runtime), eşzamanlı sıkıştırmalı kuşaksal bir toplayıcı getirdi. Yığın üç bölgeye ayrılır: Young, Mature (Old Generation'ın benzeri) ve Large Object Space (12 KB'den büyük nesneler için). Young Bölgesi toplama, çoğu durumda iş parçacıklarını durdurmadan paralel olarak gerçekleşir. Android 10+'da, Concurrent Copying tanıtıldı — sıkıştırma, Stop-The-World olmadan arka plan iş parçacığında çalışır.
ART mimarisi sayesinde tipik GC duraklamaları 2–4 ms'ye ve genç nesnelerin baskın olduğu senaryolarda 0.5–1 ms'ye düşürüldü. Bu, Android cihazların aktif bellek işlemleri sırasında bile sabit 60 FPS'yi korumasını sağladı.
Java ekosisteminde, her biri kendi performans profiline sahip birkaç GC uygulaması vardır. Android geliştirme için seçim ART ile sınırlıdır, ancak Java GC bilgisi, mobil uygulamalar için sunucu tarafı kod yazarken ve Kotlin Multiplatform ile geliştirme yaparken faydalıdır.
Serial GC, tam uygulama durdurmalı (Stop-The-World) tek iş parçacıklı bir toplayıcıdır. Her Mark, Sweep ve Compact işlemi tek bir iş parçacığı tarafından gerçekleştirilir. Performansı düşüktür — mobil sunucular için kullanılmaz. Yalnızca 100 MB'a kadar yığını olan küçük uygulamalar için uygundur.
Parallel GC (Throughput Collector olarak da bilinir), tüm toplama aşamaları için birden çok iş parçacığı kullanır. Maksimum iş hacmine (throughput) yöneliktir — uygulama çalışma süresine göre GC'de harcanan zamanı en aza indirir. JVM'de -XX:+UseParallelGC bayrağıyla etkinleştirilir.
G1 (Garbage-First) GC, Java 9+'daki varsayılan toplayıcıdır. Yığın 1–32 MB'lık bölgelere ayrılır. G1, duraklama süresini tahmin eder ve belirtilen sınır (varsayılan 200 ms) içinde kalmaya çalışır. Öncelik: en fazla çöp içeren bölgeler önce temizlenir (adı buradan gelir). G1, öngörülebilir duraklamalarla büyük yığınlı sunucular (4–64 GB) için etkilidir.
// Hedef duraklama 100 ms ile G1 GC'yi etkinleştirme
// java -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -jar app.jar
public class MemoryMonitor {
private static final long THRESHOLD = 512 * 1024 * 1024; // 512 MB
public void checkHeapUsage() {
Runtime rt = Runtime.getRuntime();
long used = rt.totalMemory() - rt.freeMemory();
if (used > THRESHOLD) {
System.out.println("Heap usage exceeded threshold: " + used);
System.out.println("Consider reducing allocations");
}
}
}
Runtime aracılığıyla yığını izlemek, bellek sızıntılarını erken aşamada tespit etmeyi sağlar. Kararlı çalışmada used maksimum yığının %80'ini aşarsa — bu, olası bir sızıntı veya uygulamanın aşırı bellek tüketimi sinyalidir.
Modern ART GC bile tüm sorunları çözmez — uygunsuz bellek kullanımı, jank ve ANR'nin (Application Not Responding) ana nedeni olmaya devam etmektedir. Ana senaryoları ve optimizasyon yöntemlerini inceleyelim.
GC Duraklamaları — toplama sırasında uygulama iş parçacıklarının durmasıdır. Ekranda bu, iki kare arasındaki süre 16.6 ms'yi (60 FPS) aştığında düşen kareler olarak kendini gösterir. GC 30 ms sürerse, iki yerine yalnızca bir kare çizilir — kullanıcı arayüzde takılma görür.
Uzun duraklamaların ana nedenleri: Old Generation'da çok sayıda canlı nesne, yığın parçalanması, sık Full GC. Teşhis için Android Studio Profiler ve systrace kullanılır.
GC dostu kodun ana kuralı, tahsis edilen nesne sayısını en aza indirmektir. Her yeni nesne yalnızca bellek tahsisi değil, aynı zamanda sonraki toplama da gerektirir. GC hızlı olsa bile, saniyede 1000 ekstra tahsis, toplayıcı için 1000 kontrol oluşturur.
Bellek sızıntısı, bir nesne artık ihtiyaç duyulmasa bile ulaşılabilir durumda kaldığında oluşur. GC böyle bir nesneyi silemez ve bellek giderek tükenir. Tipik nedenler: kaydı silinmemiş dinleyiciler, Activity'ye statik referanslar, harici bağlamı yakalayan anonim sınıflar ve kapatılmamış Cursor/InputStream.
// Bellek sızıntısı: anonim sınıf Activity referansını tutar
public void startTask() {
new Thread(new Runnable() { // örtük olarak this (Activity) tutar
@Override
public void run() {
// uzun işlem...
System.out.println("Done");
}
}).start();
}
// Düzeltme: statik iç içe sınıf + WeakReference
private static class TaskRunnable implements Runnable {
private WeakReference<Activity> activityRef;
TaskRunnable(Activity activity) {
this.activityRef = new WeakReference<>(activity);
}
@Override
public void run() {
Activity act = activityRef.get();
if (act != null) {
// Activity ile güvenli çalışma
}
}
}
Bu örnekte, anonim Runnable Activity'ye örtük bir referans yakalar. İş parçacığı canlı olduğu sürece — kullanıcı ekranı kapatmış olsa bile Activity GC tarafından toplanamaz. WeakReference + statik sınıf ile düzeltme bu zinciri kırar ve Activity'nin serbest bırakılmasını sağlar.
Sıkça Sorulan Sorular
Android'deki (ART) GC, sınırlı belleğe sahip mobil cihazlar için optimize edilmiş, eşzamanlı sıkıştırmalı kuşaksal bir toplayıcıdır. Java GC (G1, ZGC) büyük yığınlara ve öngörülebilir duraklamalara sahip sunucu tarafı toplayıcılardır. ART GC, JVM bayrakları kullanmaz — tüm ayarlar işletim sistemi düzeyinde otomatik olarak yapılır.
Stop-The-World, toplayıcının nesne grafiğini güvenli bir şekilde dolaşmak veya belleği boşaltmak için uygulamanın tüm iş parçacıklarını duraklattığı andır. STW ne kadar uzunsa jank o kadar belirgindir. ART, kuşaksal mimarisi sayesinde tipik STW süresini 2–4 ms'ye düşürdü.
Android Studio Memory Profiler'ı kullanın — yığın büyümesini, tahsis sayısını gösterir ve Heap Dump almayı sağlar. Derinlemesine analiz için LeakCanary'yi kullanın — kitaplık sızıntıları otomatik olarak tespit eder ve GC toplamayı engelleyen referans zincirini gösterir.
Full GC, Old Generation dahil tüm yığın kuşaklarının tam bir koleksiyonudur. Mobil uygulamalarda Full GC 50–200 ms sürebilir ve belirgin jank veya ANR'ye neden olabilir. Ana nedenler: yığın parçalanması, bellek sızıntıları, Old Generation eşiğinin aşılması.
Kotlin, yapılandırılmış eşzamanlılıkla coroutine'ler sağlar — kapsam iptali, tüm alt coroutine'leri otomatik olarak iptal ederek sızıntıları önler. Kotlin'de ayrıca geç başlatma için lazy delegesi ve geçici nesne sayısını azaltan kapsam işlevleri bulunur.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun