Zibil yığımı vasitəsilə avtomatik yaddaş idarəetməsi Android platformasının ART virtual maşınına əsaslanan əsas mexanizmidir. Google Android Documentation, 2026-ya gərə, zibil yığıcı tərtibatçını əl ilə yaddaş idarəetməsindən azad edir, artıq istinadı olmayan obyektləri avtomatik silir. GC olmadan hər bir obyekt ayrılması açıq şəkildə free və ya delete çağırılmasını tələb edərdi ki, bu da saniyədə milyonlarla obyekti olan Java ekosistemində fiziki cəhətdən mümkün deyil.
Əsas məqamlar
Garbage Collection (GC) — proqram tərəfindən artıq istifadə edilməyən obyektlərin tutduğu yaddaşı aşkarlama və boşaltma avtomatik prosesidir. Mobil inkişaf kontekstində GC Android platformasında ART virtual maşını, həmçinin standart Java Virtual Machine vasitəsilə tətbiq olunur.
Əl ilə yaddaş idarəetməsi olan dillərdən (C, C++) fərqli olaraq, orada proqramçı açıq şəkildə free və ya delete çağırmalıdır, GC tamamilə obyektlərin həyat dövriyyəsini izləmə vəzifəsini üzərinə götürür. Tərtibatçı new operatoru vasitəsilə yeni obyektlər yaradır, yığıcı isə obyektin çatılmaz olduğu anı müyyənləşdirir — yəni ona heç bir aktiv istinad qalmayıb.
Əsas metrika GC-nin səmərəliliyi — pauza vaxtı (pause time) və ötürmə qabiliyyəti (throughput). Pauza — yığımın aparılması üçün tətbiqin icrasının dayandırıldığı müddətdir. Mobil mühitdə 8–16 millisaniyədən uzun pauzalar buraxılmış çərçivələr (jank) kimi nəzərə çarpır.
Google I/O 2019 məlumatlarına görə, Android 10-da ART tipik GC pauzalarını 2–4 ms-ə endirdi ki, bu da Android 4.4-dəki Dalvik ilə müqayisədə 70% azdır. Bununla belə, yaddaşla səhv işləmə — dövrülərdə obyektlərin tez-tez ayrılması, lazımsız müvəqqəti nüsxələrin yaradılması — performans problemlərinin əsas səbəbi olaraq qalır.
Java və Android-də bütün GC tətbiqləri pauza vaxtı ilə təmizlik tamlığı arasında tarazlığa nail olmaq üçün birləşdirilən bir neçə fundamental alqoritmə əsaslanır. Bu alqoritmləri başa düşmək GC-friendly kod yazmaq üçün zəruridir.
Mark-and-Sweep — iki mərhələdə işləyən ən sadə alqoritmdir. Mark mərhələsində yığıcı kök istinadlardan (root set) — yerli dəyişənlər, statik sahələr, iplik yığınları — başlayaraq obyekt qrafikini gəzir. Hər çatılan obyekt canlı bayrağı ilə qeyd olunur. Sweep mərhələsində yığıcı bütün yığını gəzir və qeyd olunmamış obyektlərin yaddaşını boşaldır.
Çatışmazlıq — yaddaş fraqmentasiyası: Sweep-dən sonra boş sahələr işğal olunmuş sahələrlə növbələşir ki, bu da böyük obyektlərin ayrılmasını çətinləşdirir. Mobil ssenarilərdə bu kritikdir, çünki yığın adətən kiçikdir (Android-də 64–512 MB).
Copying Collection yığını iki yarım sahəyə (semi-spaces) bölür. Aktiv obyektlər bir yarım sahədən digərinə fasiləsiz şəkildə köçürülür. Köçürmədən sonra köhnə yarım sahə tamamilə boş elan edilir. Alqoritm fraqmentasiyanı tamamilə aradan qaldırır, lakin iki dəfə çox yaddaş tələb edir.
Mobil mühitlərdə Copying Collection nəsil yığıcıları tərəfindən statistik olaraq tez ölən gənc obyektlərin sürətli təmizlənməsi üçün istifadə olunur (zəif nəsil hipotezi).
Generational Collection yığını nəsillərə bölür: Young Generation (gənc obyektlər) və Old Generation (bir neçə yığımdan sağ çıxmış köhnələr). Gənc nəsilin yığımı (Minor GC) tez və sürətli aparılır, çünki əksər obyektlər gənc ikən ölür. Köhnə nəsilin yığımı (Major GC və ya Full GC) daha az baş verir, lakin daha uzun çəkir.
// Nəsilli GC-nin nümayisi: gənc obyektlər tez ölür
void processItems(List<Item> items) {
List<Result> results = new ArrayList<>(); // bütün metod boyu yaşayır
for (Item item : items) {
Result r = new Result(item.getValue()); // dərhal ölür
if (r.isValid()) {
process(r); // r zibilə çevrilir
}
}
saveResults(results); // results Old Gen-ə keçir
}
Bu nümunədə Result obyektləri dövrənin içində yaradılır və dərhal zibilə çevrilir — onlar Young GC üçün ideal namizədlərdir. results obyekti daha uzun yaşayır və Old Generation-a keçir. Nəsillərə bölgü Minor GC-yə köhnə yığına toxunmadan gənc obyektləri millisaniyələrdə təmizləməyə imkan verir.
Android Dalvik VM-dən ART (Android Runtime)-a qədər yol keçdi və GC tətbiqi onlar arasındakı əsas fərqlərdən biridir. Android-də GC arxitekturasını başa düşmək real cihazlarda pauzaları minimuma endirən kod yazmağa kömək edir.
| Xarakteristikası | Dalvik (4.4-dək) | ART (5.0+) |
|---|---|---|
| GC növü | Concurrent Mark ilə Mark-and-Sweep | Nəsilli + Concurrent |
| Tipik pauza | 10–30 ms | 2–4 ms |
| Kompaktlaşdırma | Xeyr (yalnız fraqmentasiya artır) | Bəli (fon rejimində, tətbiqi dayandırmadan) |
| AOT-kompilyasiya | JIT (Just-In-Time) | AOT + JIT (hibrid) |
Dalvik concurrent fazası ilə Mark-and-Sweep kombinasiyasından istifadə edirdi. Concurrent Mark tətbiqə obyekt qrafikini gəzmə zamanı işləməyə davam etməyə imkan verirdi, lakin Sweep mərhələsi bütün ipliklərin dayandırılmasını (Stop-The-World) tələb edirdi. Az miqdarda RAM (512 MB — 1 GB) olan cihazlarda pauzalar 30 ms-ə çatırdı ki, bu da interfeysdə nəzərə çarpan ləngimələrə səbəb olurdu. Bundan əlavə, Dalvik yığını kompaktlaşdırmırdı, buna görə də uzun müddətli işdən sonra fraqmentasiya artır və böyük obyektlərin (məsələn, Bitmap) ayrılması kifayət qədər ümumi boş yaddaş olsa belə OutOfMemoryError verə bilərdi.
ART (Android Runtime) concurrent kompaktlaşdırma ilə nəsilli yığıcı tətbiq etdi. Yığın üç regiona bölünür: Young, Mature (Old Generation analoqu) və Large Object Space (12 KB-dan böyük obyektlər üçün). Young Region yığımı əksər hallarda iplikləri dayandırmadan paralel şəkildə aparılır. Android 10+-da Concurrent Copying meydana çıxdı — kompaktlaşdırma Stop-The-World olmadan fon iplikdə aparılır.
ART arxitekturası sayəsində tipik GC pauzaları 2–4 ms-ə endi, gənc obyektlərin üstünlük təşkil etdiyi ssenarilərdə isə 0.5–1 ms-ə qədər azaldı. Bu, Android cihazlarına aktiv yaddaş işində belə stabill 60 FPS təmin etməyə imkan verdi.
Java ekosistemində hər biri öz performans profilinə malik bir neçə GC tətbiqi var. Android inkişafı üçün seçim ART ilə məhduddur, lakin Java GC haqqında bilik mobil tətbiqlərin server hissəsini yazarkən və Kotlin Multiplatform-da inkişaf edərkən faydalıdır.
Serial GC — tətbiqin tam dayandırılması ilə (Stop-The-World) tək iplikli yığıcı. Hər bir Mark, Sweep və Compact əməliyyatı bir iplik tərəfindən yerinə yetirilir. Performans aşağıdır — mobil serverlər üçün tətbiq edilmir. Yalnız 100 MB-dək yığını olan kiçik tətbiqlər üçün uyğundur.
Parallel GC (həmçinin Throughput Collector kimi tanınır) bütün yığım mərhələləri üçün bir neçə iplik istifadə edir. Maksimum ötürmə qabiliyyətinə (throughput) yönəlib — GC-yə sərf olunan vaxtı tətbiqin iş vaxtına nisbətdə minimuma endirir. JVM-də -XX:+UseParallelGC bayrağı vasitəsilə aktivləşdirilir.
G1 (Garbage-First) GC — Java 9+-da defolt yığıcı. Yığın 1–32 MB-lıq regionlara bölünür. G1 pauza vaxtını proqnozlaşdırır və verilmiş limitə (defolt 200 ms) sığmağa çalışır. Prioritet: ən çox zibil olan regionlar əvvəlcə təmizlənir (adı da buradan gəlir). G1 böyük yığınlı serverlər (4–64 GB) və proqnozlaşdırıla bilən pauzalar üçün səmərəlidir.
// Hədəf pauzası 100 ms olan G1 GC-nin aktivləşdirilməsi
// 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("Yığın istifadə həddi aşıldı: " + used);
System.out.println("Ayırmaları azaltmağı düşünün");
}
}
}
Runtime vasitəsilə yığının monitorinqi erkən mərhələdə yaddaş sızıntılarını aşkarlamağa imkan verir. Stabil işdə used maksimal yığının 80%-dən çox olarsa — bu, mümkün yaddaş sızıntısı və ya tətbiq tərəfindən həddən artıq yaddaş istehlakı siqnalıdır.
Hətta müasir ART GC bütün problemləri həll etmir — yaddaşın düzgün istifadə edilməməsi jank və ANR-nin (Application Not Responding) əsas səbəbi olaraq qalır. Əsas ssenariləri və optimizasiya metodlarını nəzərdən keçirək.
GC Pauses — yığım zamanı tətbiq ipliklərinin dayandırılması. Ekranda bu, iki çərçivə arasındakı vaxt 16.6 ms-dən (60 FPS) çox olduqda buraxılmış çərçivələr kimi özünü göstərir. GC 30 ms çəkərsə, iki çərçivə əvəzinə yalnız biri çəkilir — istifadəçi interfeysdə ləngimə görür.
Uzun pauzaların əsas səbəbləri: Old Generation-da çox sayda canlı obyekt, yığın fraqmentasiyası, tez-tez Full GC. Diaqnostika üçün Android Studio Profiler və systrace istifadə olunur.
Əsas qayda GC-friendly kod — ayrılan obyektlərin sayını minimuma endirmək. Hər yeni obyekt təkcə yaddaşın ayrılmasını deyil, həm də sonradan yığımı tələb edir. GC sürətli olsa belə, saniyədə 1000 lazımsız ayırma yığıcıya 1000 yoxlama verir.
Yaddaş sızıntısı obyekt çatılan olaraq qaldıqda baş verir, baxmayaraq ki, artıq lazım deyil. GC belə bir obyekti silə bilməz və yaddaş tədricən tükənir. Tipik səbəblər: qeydiyyatdan çıxarılmamış dinləyicilər, Activity-yə statik istinadlar, xarici konteksti tutan anonim siniflər və bağlanmamış Cursor/InputStream.
// Yaddaş sızıntısı: anonim sinif Activity-yə istinad saxlayır
public void startTask() {
new Thread(new Runnable() { // gizli şəkildə this (Activity) saxlayır
@Override
public void run() {
// uzun əməliyyat...
System.out.println("Hazır");
}
}).start();
}
// Düzəliş: statik iç içə sinif + 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 ilə təhlükəsiz iş
}
}
}
Bu nümunədə anonim Runnable Activity-yə gizli istinad tutur. İplik canlı olduğu müddətçə — istifadəçi ekranı bağlasa belə, Activity GC tərəfindən yığıla bilməz. WeakReference + static class düzəlişi bu zənciri qırır və Activity-nin utilizasiyasına imkan verir.
Tez-tez verilən suallar
Android-də GC (ART) — məhdud yaddaşlı mobil cihazlar üçün optimallaşdırılmış, concurrent kompaktlaşdırma ilə nəsilli yığıcıdır. Java GC (G1, ZGC) — böyük yığınlar və proqnozlaşdırıla bilən pauzalarla server yığıcılarıdır. ART GC JVM bayraqlarından istifadə etmir — bütün konfiqurasiya əməliyyat sistemi səviyyəsində avtomatik aparılır.
Stop-The-World — yığıcının obyekt qrafikində təhlükəsiz gəzmək və ya yaddaşı boşaltmaq üçün tətbiqin bütün ipliklərini dayandırdığı andır. STW nə qədər uzun olsa, jank bir o qədər nəzərə çarpardı. ART nəsilli arxitektura sayəsində tipik STW vaxtını 2–4 ms-ə endirdi.
Android Studio Memory Profiler istifadə edin — yığının artımını, ayırmaların sayını göstərir və Heap Dump etməyə imkan verir. Dərin təhlil üçün LeakCanary tətbiq edin — kitabxana avtomatik olaraq sızıntıları aşkarlayır və GC yığımına mane olan istinad zəncirini göstərir.
Full GC — Old Generation daxil olmaqla bütün nəsil yığınlarının tam yığımıdır. Mobil tətbiqlərdə Full GC 50–200 ms çəkə bilər, nəzərə çarpan jank və ya ANR səbəb olur. Əsas səbəblər: yığın fraqmentasiyası, yaddaş sızıntıları, Old Generation həddinin aşılması.
Kotlin strukturlaşdırılmış konkurentlik ilə korutinlər təmin edir — scope ləğv edilməsi avtomatik olaraq bütün uşaq korutinləri ləğv edir, sızıntıların qarşısını alır. Həmçinin Kotlin-də tənbəl inisializasiya üçün lazy delegatı və müvəqqəti obyektlərin sayını azaldan görünmə şərh əməliyyatları var.
Nəticələr
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun