StrictMode: mi ez, a szigorú szabályok módja és debuggolás Androidon

Szerző: IT Sectr Megjelenés: 2026-03-31 Olvasási idő: 8 perc

StrictMode egy beépített fejlesztői eszköz az Android SDK-ban, amely valós időben észleli és jelenti a fő szálon végzett véletlen I/O-műveleteket és hálózati hívásokat. Nem javítja a hibákat, hanem detektorként működik — kivételt dob vagy a LogCat-be ír, ha egy beállított szabályzatot megsértenek. A Google, 2024 adatai szerint a StrictMode helyes beállításával a teljesítményproblémák akár 80%-a már az alkalmazás megjelenése előtt felderíthető.

A legfontosabb

  • StrictMode — az Android fő szálán elkövetett teljesítmény-sértések detektora
  • A lemez-szabályzatok (disk_read, disk_write) és a hálózat (network) képezik az alapellenőrzések halmazát
  • Az eszköz nem javítja a problémákat, hanem a LogCat-en, párbeszédablakon vagy crash-en keresztül értesít róluk
  • A beállítás az Application.onCreate-ben történik, és a setThreadPolicy + setVmPolicy módszereket használ
  • Penalty-módok: kivétel dobása (death), naplózás, értesítés a dropboxba

Mi az a StrictMode

StrictMode egy API, amely az API Level 9 (Android 2.3 Gingerbread) óta része az Android SDK-nak. Feladata, hogy futásidőben felderítse a fő (UI) szálon végrehajtott, nem szándékos nehéz műveleteket, amelyek blokkolhatják a felület megjelenítését. A fő szál felelős a felhasználói bevitel feldolgozásáért, a layout kiszámításáért és a megjelenítésért — minden 16 ms-nál hosszabb blokkolás kimaradt képkockát (frame drop) eredményez.

Az eszköz filozófiája

StrictMode a „fail fast” elvet követi — minél korábban, lehetőleg az első megjelenéskor fedezd fel a problémát. Ahelyett, hogy a felhasználók lassulásra vonatkozó panaszára várna, a fejlesztő jelet kap (naplók, párbeszédablak vagy crash) már a fejlesztés során. Az eszköz nem igényel extra könyvtárakat vagy Gradle-konfigurációt — néhány sornyi kód a Application.onCreate-ban elég, és minden eszközön automatikusan működik.

Célközönség

A StrictMode minden Android-fejlesztőnek szól, tapasztalattól függetlenül. A kezdőknek segít jó szokásokat kialakítani (ne küldj hálózati kéréseket az UI-szálon), a tapasztaltaknak automatizálja a minőségellenőrzést a CI/CD pipeline-ban. A nagy projektek (Google, Uber, Spotify) penaltyDeath-dzsel kapcsolják be a StrictMode-ot a debug-verziókban, a release-verziókban pedig a BuildConfig.DEBUG ellenőrzésével kapcsolják ki.

Hogyan működik a StrictMode

StrictMode elkapja azokat a rendszerhívásokat, amelyek blokkolhatják a szálat, és összehasonlítja őket az aktív szabályzatok halmazával. Ha egy hívás megfelel egy szabályzatnak, és a fő szálon fut, a StrictMode alkalmazza a beállított büntetést (penalty). Az elkapási mechanizmus folyamaton belüli hook-on keresztül valósul meg — nem használ reflectiont, és minimális overheaddel működik.

A detektálás mechanizmusa

Egy szabályzat aktiválásakor a StrictMode a saját kezelőjét illeszti be a rendszerhívások belépési pontjába (FileInputStream, FileOutputStream, Socket, URLConnection). Amikor az alkalmazás például URLConnection.openStream-et hív a fő szálon, a StrictMode ellenőrzi az aktuális szálat — ha ez a main thread, az eszköz bekapcsol. Android 6.0+ rendszeren a mechanizmus megerősített: a main thread-en történő hálózati hívások StrictMode nélkül is NetworkOnMainThreadException-t generálnak, de a StrictMode a disk I/O felett is ellenőrzést biztosít.

Penalty (büntetés)

Minden szabályzatnak lehet saját penalty-típusa vagy kombinációja: penaltyLog — írás a LogCat-be stacktrace-szel, penaltyDialog — párbeszédablak megjelenítése a felhasználónak (csak debug-ban), penaltyDeath — kivétel dobása és az alkalmazás összeomlása, penaltyDropBox — adatok mentése a DropBoxManagerbe későbbi elemzéshez. A CI/CD pipeline-hoz a penaltyDeath ajánlott — ez garantálja, hogy egyetlen, szabályzatot sértő merge sem marad észrevétlen.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

StrictMode-szabályzatok

A StrictMode két szintre osztja a szabályzatokat: ThreadPolicy (szálszintű — mit nem szabad a fő szálon csinálni) és VmPolicy (virtuális gép szintű — memória- és erőforrás-szivárgások). Mindkét szint egymástól függetlenül állítható be, és párhuzamosan működik.

ThreadPolicy: lemez és hálózat

Szálszinten a StrictMode négyféle sértést ellenőriz: lemezről olvasás (detectDiskReads), lemezre írás (detectDiskWrites), hálózati műveletek (detectNetwork) és egyéni lassú hívások (detectCustomSlowCalls). A disk_read minden SharedPreferences, SQLite vagy fájl olvasásakor aktiválódik a fő szálon. A network — HTTP-kérések, WebSocket, Socket-kapcsolatok esetén. Android 11+-ban megjelent a detectUnbufferedIO a puffer nélküli I/O felderítésére.

VmPolicy: memóriaszivárgások

A VmPolicy az ART virtuális gép szintjén ellenőrzi a szivárgásokat: detectActivityLeaks (nem megsemmisített Activity-k), detectLeakedClosableObjects (le nem zárt Cursor, Stream, Socket), detectLeakedRegistrationObjects (le nem regisztrált BroadcastReceiver, ServiceConnection). Ha a VmPolicy azt észleli, hogy egy Activity létrejött, de az onDestroy hívása után nem semmisült meg, teljes stack trace-t ad ki — ez órákat spórol meg a memóriaszivárgások hibakeresésében.

SzabályzatSzintMit észlel
detectDiskReadsThreadSharedPrefs, SQLite, fájlok olvasása az UI-szálon
detectDiskWritesThreadÍrás SharedPrefs-be, SQLite-ba, fájlokba az UI-szálon
detectNetworkThreadBármilyen hálózati művelet az UI-szálon
detectActivityLeaksVMAz onDestroy-t túlélő Activity-k
detectLeakedClosableObjectsVMLe nem zárt Cursor, Stream, Socket

Egyéni címkék (customSlowCall)

A detectCustomSlowCalls segítségével saját metódusokat jelölhetsz meg „gyanús”-ként, és figyelmeztetést kapsz, ha túllépik a beállított küszöbértéket. Például, ha a loadUserProfile() metódusod általában 5 ms-ig fut, de néha 200 ms-ig, csavard be a StrictMode.noteSlowCall("loadUserProfile") hívásba. Ha az időtartam meghaladja a küszöböt (alapértelmezés szerint 2000 ms), a StrictMode penalty-t generál. A küszöb a setSlowCallDurationThreshold beállítással módosítható.

Hogyan állítsd be a StrictMode-ot

A StrictMode alapszintű beállítása 10 sornyi kódot igényel, és az egyéni Application-osztály onCreate metódusában történik. A fő szabály: a StrictMode-ot csak debug-verziókban kapcsold be — release-verziókban lelassítja az alkalmazást, és hamis riasztásokat okozhat.

Alapszintű konfiguráció

Hozz létre egy Application-ből származó osztályt, regisztráld az AndroidManifest.xml-ben az android:name attribútummal, és add hozzá a StrictMode-konfigurációt. A ThreadPolicy.Builder bekapcsolja az összes detektort és az összes penalty-típust (kivéve a dialog-ot — az csak akkor működik, ha debugger csatlakozik). A VmPolicy.Builder hozzáadja az Activity- és Closable-szivárgás-detektorokat. Nagy projektekhez (100+ képernyő) ajánlott a VmPolicy beállítása penaltyDeath-dzsel az Activity Leaks detektorra — ez szigorú, de hatékony.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setVmPolicy(
                StrictMode.VmPolicy.Builder()
                    .detectActivityLeaks()
                    .detectLeakedClosableObjects()
                    .detectLeakedRegistrationObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Integráció a CI/CD-be

Az automatikus ellenőrzéshez a CI/CD-ben használj penaltyDeath-et — ha egy teszt megsérti a szabályzatot, az alkalmazás kivétellel összeomlik. Kombináld az Android Test Orchestratorral, hogy minden teszt tiszta folyamatban fusson. Az UI-tesztekhez (Espresso, Compose Test) írj egyéni TestRule-t, amely elkapja a StrictMode-sértéseket, és assertion-hibává alakítja. Példa: @Before-ben kapcsold be a StrictMode-ot, @After-ban pedig ellenőrizd, hogy nem volt violations.

Küszöbértékek beállítása

Alapértelmezés szerint a customSlowCall küszöbe 2000 ms, a disk_read és disk_write esetén pedig nincs küszöb (minden művelet triggerel). A setSlowCallDurationThreshold és a setSlowIoDurationThreshold segítségével saját értékeket adhatsz meg ezredmásodpercben. Ha az alkalmazásod jogszerűen olvas SharedPreferences-t a fő szálon (kis konfiguráció), emeld a küszöböt 10–20 ms-ra — ez kiszűri a gyors olvasásokat, de megtartja a lassakat.

StrictMode bevált gyakorlatok

StrictMode hatékony, de szeszélyes eszköz. A rossz beállítás milliónyi hamis riasztást eredményez, amitől a fejlesztők már nem is figyelnek rájuk. Az alábbiakban nagy Android-csapatok tapasztalatából összegyűjtött, kipróbált gyakorlatok következnek.

Csak debug-verziókban kapcsold be

Ez egy vasszabály: a StrictMode SOHA ne legyen aktív release-verziókban. Használd a BuildConfig.DEBUG jelölőt vagy egy egyéni buildConfigField-et. A release-verziókban sok harmadik féltől származó könyvtár jogszerűen végez műveleteket a fő szálon (SDK-inicializáció, gyorsítótár-írás), és a StrictMode hamis riasztásokat generál. Ráadásul a penaltyDialog release-verzióban párbeszédablakot mutat a végfelhasználónak — ami elfogadhatatlan.

Három szigorúsági szintet használj

Kis projekteknél (1–10 képernyő) állítsd be a penaltyLog-ot — a naplók elegendőek a kézi elemzéshez. Közepes projekteknél (10–50 képernyő) adj hozzá penaltyDeath-et a network és a customSlowCalls esetén. Nagy projekteknél (50+ képernyő) kapcsold be a teljes szabályzatkészletet penaltyDeath-dzsel a CI/CD-ben, a helyi fejlesztéshez pedig penaltyLog-ot. Ez a fokozatosság nem terheli túl a fejlesztőt hamis crash-ekkel, de szigorúan ellenőrzi a minőséget a pipeline-ban.

Hamis riasztások kezelése

Néhány könyvtár (Firebase, Crashlytics, Adjust) jogszerűen végez háttérműveleteket, amelyeket a StrictMode tévesen észlelhet. Megoldások: add a könyvtárat a whitelist-hez a penaltyListener segítségével, frissítsd a könyvtárat olyan verzióra, amely kifejezetten háttérszálra vált, vagy használd a StrictMode.vmPolicy-t. Android 11+-ban megjelent a StrictMode.OnVmViolationListener a sértések programozott szűrésére stacktrace alapján.

kotlin
// A false positive-ok szűrése a penaltyListener segítségével
StrictMode.setThreadPolicy(
    StrictMode.ThreadPolicy.Builder()
        .detectAll()
        .penaltyListener { violation ->
            val stack = violation.stackTraceToString()
            if ("com.google.firebase" !in stack) {
                logViolation(violation)
            }
        }
        .build()
)

StrictMode vs Android Lint vs profilozók

A StrictMode nem az egyetlen minőségellenőrző eszköz az Android-ökoszisztémában. Hogy megértsük a helyét, hasonlítsuk össze az Android Lint, az Android Profiler és a Perfetto eszközökkel a kulcskritériumok szerint: az ellenőrzés ideje, az elemzés mélysége és az automatizálás.

KrítériumStrictModeAndroid LintProfiler / Perfetto
Az ellenőrzés idejeRuntime (az alkalmazás futása közben)Compile time (a futtatás előtt)Runtime (post-mortem)
Mit ellenőrizLemez, hálózat, szivárgásokXML, kód, erőforrásokCPU, memória, hálózat, energia
AutomatizálásCI/CD a penaltyDeath-en keresztülGradle-feladat + lint-baselineKézi elemzést igényel
MélységCsak UI-szál és szivárgásokStatikus kódelemzésTeljes teljesítménykép
Hamis riasztásokKözepes (könyvtáraktól függ)Alacsony (beállított szabályok)Nincs (tényleges mérések)

A legjobb stratégia mindhárom megközelítés kombinálása: az Android Lint a fordítási fázisban elkapja a nyilvánvaló hibákat (például az elfelejtett IdleHandler-t), a StrictMode futásidőben észleli a problémákat, az Android Profiler / Perfetto pedig mélyreható elemzésre használható, amikor az első két eszköz nem ad választ. Valós projektekben (Google Maps, Instagram) a StrictMode-ot a fejlesztés második hetében vezetik be — közvetlenül az alaparchitektúra beállítása után.

Kódpéldák a StrictMode-mal

Nézzünk két valós forgatókönyvet, ahol a StrictMode segít feltárni és megszüntetni a teljesítményproblémákat: a SharedPreferences olvasása a fő szálon, és Activity-szivárgás egy le nem regisztrált callback miatt.

Lassú SharedPreferences észlelése

Az alkalmazás indításakor a StrictMode a detectDiskReads szabályzattal észleli a SharedPreferences olvasását a fő szálon. Megoldás: töltsd be a konfigurációt aszinkron módon a CoroutineScope-on keresztül, vagy gyorsítótárazd memóriában az indításkor. A SharedPreferences szinkron módon olvassa a lemezről az XML-fájlt — kis fájl (1–2 KB) esetén is 1–5 ms-ig tart a művelet, olcsó eszközökön pedig akár 20 ms-ig is, ami kimaradt képkockát okozhat.

kotlin
// ❌ Problémás kód — SharedPrefs olvasása az UI-szálon
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // StrictMode detectDiskReads → VIOLATION!
        prefs = getSharedPreferences("config", MODE_PRIVATE)
    }
}

// ✅ Javított kód — olvasás Coroutine-on keresztül
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadConfigAsync()
    }
}

Activity-szivárgás észlelése

A StrictMode a VmPolicy.detectActivityLeaks segítségével észleli az Activity-t, amely kikerült a stackből (a finish meghívva), de az Activity-objektum statikus hivatkozás vagy le nem regisztrált callback miatt továbbra is a memóriában marad. Tipikus forgatókönyv: EventBus vagy LocationListener regisztrálása a onResume-ben a onPause-ban történő unregister hívása nélkül. A VmPolicy stacktrace-t ad ki, megjelölve azt a sort, ahol a hivatkozás létrejött.

kotlin
// ❌ Szivárgás — a callback nincs leregisztrálva
private var locationCallback: LocationCallback? = null

override fun onResume() {
    super.onResume()
    locationCallback = LocationCallback(this::onLocationUpdated)
    locationManager.register(locationCallback) // StrictMode → LEAK!
}

override fun onPause() {
    super.onPause()
    // Elfelejtetted: locationManager.unregister(locationCallback)
}

Gyakran ismételt kérdések

Lelassítja a StrictMode az alkalmazást?

A StrictMode valóban hozzáad egy kis overheadet — minden rendszerhívást ellenőriz a szabályzatoknak való megfelelésre. A teljesítményre gyakorolt hatás 1–3% debug-verzióban, release-ben pedig nincs (ott a StrictMode ki van kapcsolva). A detectAll bekapcsolásakor régebbi eszközökön (Android 6–8) az overhead elérheti az 5%-ot, ezért javasolt csak a szükséges szabályzatokat beállítani.

Használható a StrictMode Jetpack Compose-zal?

Igen, a StrictMode teljes mértékben kompatibilis a Jetpack Compose-zal. A disk és network szabályzatok a keretrendszer szintjén működnek, függetlenül az UI-keretrendszertől. Sőt, a Compose-ban az UI-blokkolások kritikussága nagyobb — a Compose 120 FPS-sel rajzolja a képkockákat a magas frissítési frekvenciájú eszközökön, ezért a fájlolvasásra fordított plusz 5 ms észrevehetőbb.

Miért nem működik a StrictMode a SharedPreferences olvasásakor?

Android 8.1 (API 27) óta a SharedPreferences használhat memóriagyorsítótárat — ha a fájlt már beolvasták, az ismételt olvasás nem váltja ki a StrictMode-ot. Ellenőrizd, hogy először hívod-e meg a getSharedPreferences-t (hideg olvasás), és hogy a detectDiskReads szabályzat aktív-e. Ellenőrizd azt is, hogy a StrictMode-ot nem írták-e felül parent-free fragmentben.

Hogyan kapcsoljam ki a StrictMode-ot egyes tesztekhez?

JUnit-tesztekben használd a StrictMode.allowThreadDiskReads() és StrictMode.allowThreadDiskWrites() metódusokat a @Before-ban, a @After-ban pedig a StrictMode.enableDefaults() segítségével állítsd vissza a beállításokat. Instrumentation-tesztekhez használj egyéni TestRunner-t az eredeti szabályzat ideiglenes mentésével. Espresso-tesztekben kényelmes a StrictMode-kitett kódot IdlingResource-be csomagolni.

Kell-e StrictMode a Kotlin Multiplatformban?

A StrictMode csak az Android-platformon működik az Android SDK-n keresztül. A Kotlin Multiplatformban (KMP) a commonMain kód nem használhat StrictMode-ot, de az androidMain-hez hozzáadhatod a szokásos módon. Az iOS-részhez használj megfelelőt — a DispatchQueue.main.async assertion-t a fő szálhoz.

Összegzés

  • StrictMode — az Android fő szálán felmerülő teljesítményproblémák futásidőben működő detektora
  • A szabályzatok ThreadPolicy-ra (lemez, hálózat) és VmPolicy-ra (memóriaszivárgások) oszlanak
  • A beállítás 10 sornyi kódot igényel az Application.onCreate-ban a BuildConfig.DEBUG ellenőrzésével
  • A CI/CD-hez használj penaltyDeath-et — a szabályzatsértés az alkalmazás összeomlását eredményezi
  • A StrictMode nem helyettesíti, hanem kiegészíti az Android Lint-et és a Perfetto-t
  • A hamis riasztások helyes szűrése az eszköz hatékony használatának kulcsa
  • Javasolt a StrictMode bevezetése a projekt fejlesztésének második hetében

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is