Common Memory Leaks in Healthcare Apps: Causes and Fixes
SUSA’s autonomous exploration uploads the APK or web URL and runs through user‑centric flows. When a leak blocks garbage collection, the platform records an ANR or crash and flags the offending screen
What causes memory leaks in healthcare apps (technical root causes)
- Static or singleton managers – Global
Application-level singletons that hold references toActivity,Fragment, orServiceinstances prevent garbage collection. - Improper lifecycle handling –
Fragmentinstances retained after configuration changes,BroadcastReceiverregistered withoutunregister, orViewModelscoped incorrectly. - Large bitmap or image caches – Unbounded
LruCacheor custom loaders that never evict oldBitmapobjects, especially when handling patient PDFs, X‑ray images, or DICOM files. - Unbounded RxJava/ Kotlin Flow streams – Subscriptions kept alive in background threads, causing reference cycles with
BehaviorSubjectorReplaySubject. - WebView and WebViewClient leaks –
WebViewinstances not cleared after loading health portals, leaving native references to JavaScript objects. - Database cursor or ORM object retention – Cursors kept open across activity transitions, or Hibernate/Room DAOs storing entity references beyond the transaction.
- Network listeners and callback managers –
OkHttporRetrofitinterceptors that captureContextin anonymous inner classes, or custom event buses that never unregister listeners.
SUSA’s autonomous exploration uploads the APK or web URL and runs through user‑centric flows. When a leak blocks garbage collection, the platform records an ANR or crash and flags the offending screen in its coverage analytics, surfacing the root cause without manual scripting.
Real-world impact (user complaints, store ratings, revenue loss)
- App crashes during vital sign monitoring – Patients using real‑time ECG or glucose tracking see the app freeze, leading to emergency alerts being missed.
- Slow navigation after onboarding – New users report lag when switching between appointment booking and medical history, reducing conversion rates.
- Battery drain and overheating – Persistent background threads keep the device CPU busy, causing users to uninstall the app and leaving negative reviews.
- Accessibility failures – Retained UI elements prevent screen readers from updating, violating WCAG 2.1 AA and triggering compliance penalties.
- Data loss in sync cycles – Leaked network buffers cause incomplete upload of patient records, resulting in duplicate entries and revenue loss from rework.
Each of these symptoms appears in SUSA’s regression reports as a FAIL verdict on the affected flow, with a clear link to the leaking component.
5‑7 specific examples of how memory leaks manifests in healthcare apps
| # | Leak Example | Typical Manifestation in Healthcare Apps |
|---|---|---|
| 1 | Fragment retained after screen rotation | The patient’s medication list disappears after device rotation, forcing a reload. |
| 2 | Unreleased Bitmap cache for medical images | Scrolling through a radiologist’s image gallery causes gradual UI lag and eventual OOM crashes. |
| 3 | RxJava subscription never disposed | Real‑time heart‑rate updates keep the UI thread busy, leading to ANR dialogs. |
| 4 | WebView memory leak | Loading a telemedicine video‑call URL consumes increasing heap, eventually causing the app to restart. |
| 5 | Database cursor retained across activities | Opening a patient’s lab history leaves a cursor open, blocking the next screen from loading. |
| 6 | Static singleton holding Activity reference | The app’s HealthManager singleton prevents the main activity from being collected, causing a memory leak detected by LeakCanary. |
| 7 | Network listener capturing Context | A custom OkHttp interceptor retains a Context reference, leading to delayed cleanup after logout. |
How to detect memory leaks (tools, techniques, what to look for)
Tools for Android
- Android Studio Memory Profiler – Live heap monitoring while SUSA executes a flow. Look for increasing
Allocatedsize without corresponding deallocation. - LeakCanary – Automatically runs in the test build; SUSA can integrate LeakCanary via its CLI agent to flag leaks during autonomous runs.
- HPROF dump analysis – Trigger a heap dump after a crash; use
android studio > Dump Heapto identify retained objects. - Systrace + Memory tracking – Correlate UI frame drops with allocations; useful when SUSA reports ANR on a login flow.
Tools for Web (Playwright)
- Chromium DevTools – Monitor JavaScript heap size while SUSA navigates through appointment scheduling pages.
- Node.js
--inspect– Attach a debugger to catch circular references in patient data handling.
SUSA’s autonomous detection
- Upload APK or web URL → SUSA runs 10 personas (curious, impatient, elderly, adversarial, novice, student, teenager, business, accessibility, power user).
- Each persona triggers a series of flows (login, registration, checkout, search).
- When a flow exceeds a predefined memory threshold, SUSA logs a memory leak failure, links it to the UI element, and auto‑generates a regression script (Appium for Android, Playwright for Web).
How to fix each example (code-level guidance where applicable)
1. Fragment retained after screen rotation
Problem – Fragment is recreated but the old instance stays referenced.
Fix – Ensure the Fragment implements onDestroyView() and clears any static references. Use ViewBinding instead of findViewById.
class MedicationFragment : Fragment() {
private var _binding: FragmentMedicationBinding? = null
val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
2. Unreleased Bitmap cache for medical images
Problem – Cache grows without bound.
Fix – Use a bounded LruCache with a max size based on screen resolution. Clear the cache on app backgrounded state.
class ImageLoader {
private val cache = LruCache<String, Bitmap>(MAX_CACHE_SIZE)
fun load(url: String): Bitmap? {
val bitmap = cache.get(url)
if (bitmap != null) return bitmap
val newBmp = fetchBitmapFromNetwork(url)
cache.put(url, newBmp)
return newBmp
}
}
3. RxJava subscription never disposed
Problem – Subscriptions linger after the UI disappears.
Fix – Keep a CompositeDisposable scoped to the LifecycleOwner and dispose in onDestroy.
class VitalSignsViewModel : ViewModel() {
private val disposables = CompositeDisposable()
fun startMonitoring() {
disposables.add(
Observable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { /* update UI */ }
)
}
override fun onCleared() {
disposables.clear()
super.onCleared()
}
}
4. WebView memory leak
Problem – WebView retains JavaScript objects after page unload.
Fix – Call webView.clearHistory(), webView.clearCache(true), and set webView = null in onPause.
class TelemedicineActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onDestroy() {
webView.clearHistory()
webView.clearCache(true)
webView.destroy()
super.onDestroy()
}
}
5. Database cursor retained across activities
Problem – Cursor not closed after query.
Fix – Use CursorLoader or LiveData with Room. Close cursor in `
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free