Skip to content

Android: memory leak in AndroidThreadAlphaSynthWorkerPlayer #2621

@AndreiGorelov

Description

@AndreiGorelov

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Memory leak on Android after repeatedly opening and closing a view that uses alphaTab.
Each time a new playback session with a new file (important) is started, previous AndroidSynthOutput and AndroidAudioWorker instances stay in memory along with the entire Activity that hosts AlphaTabView.
AndroidThreadAlphaSynthWorkerPlayer.destroy() stops the worker thread but never clears _workerQueue or releases _player, so the queue retains lambda references indefinitely.
Multiple leaked AudioTrack threads and UI Activities accumulate until audio playback becomes distorted (some stuttering/wheezing). Logcat is heavily clogged with GC messages such as:

...
2026-03-26 20:08:53.626 27577-27586 I Background concurrent copying GC freed 368KB AllocSpace bytes, 6836(133MB) LOS objects, 17% free, 113MB/137MB, paused 109us,49us total 110.531ms
2026-03-26 20:08:53.783 27577-27586 I Background concurrent copying GC freed 336KB AllocSpace bytes, 6232(121MB) LOS objects, 17% free, 116MB/140MB, paused 234us,80us total 105.761ms
2026-03-26 20:08:54.238 27577-27586 I Background concurrent copying GC freed 304KB AllocSpace bytes, 5707(111MB) LOS objects, 15% free, 127MB/151MB, paused 71us,94us total 105.239ms
2026-03-26 20:08:54.440 27577-27586 I Background concurrent copying GC freed 400KB AllocSpace bytes, 7655(149MB) LOS objects, 15% free, 134MB/158MB, paused 116us,189us total 142.925ms
2026-03-26 20:08:54.631 27577-27586 I Background concurrent copying GC freed 320KB AllocSpace bytes, 6097(119MB) LOS objects, 12% free, 172MB/196MB, paused 176us,58us total 126.171ms
2026-03-26 20:08:54.819 27577-27586 I Background concurrent copying GC freed 464KB AllocSpace bytes, 8876(173MB) LOS objects, 16% free, 117MB/141MB, paused 115us,44us total 111.815ms
2026-03-26 20:08:55.103 27577-27586 I Background concurrent copying GC freed 384KB AllocSpace bytes, 7170(140MB) LOS objects, 18% free, 105MB/129MB, paused 130us,56us total 106.542ms
2026-03-26 20:08:55.283 27577-27586 I Background concurrent copying GC freed 384KB AllocSpace bytes, 7481(146MB) LOS objects, 15% free, 134MB/158MB, paused 115us,52us total 120.942ms
...

The leak is clearly visible in a heap dump:  AndroidSynthOutput and AndroidAudioWorker instances from previous sessions remain reachable via AndroidThreadAlphaSynthWorkerPlayer.workerQueue and its pending lambda tasks.

Image

Expected Behavior

After Activity.onDestroy and the corresponding AlphaTab API destroy call, all internal resources of AlphaTab must be released (in particular, no AndroidSynthOutput or AndroidAudioWorker instances should persist in heap).

Steps To Reproduce

  1. Create a simple Android app that hosts AlphaTab with playback enabled.
  2. Load a MusicXML score and start playback, then close the Activity.
  3. Reopen the Activity with another MusicXML score and start playback, then close the Activity.
  4. Repeat steps 2–3 about 5–10 times (switching between the same two files is enough).
  5. Observe memory usage or create a heap dump - multiple activity, AndroidAudioWorker and AndroidSynthOutput objects remain alive.

Link to jsFiddle, CodePen, Project

No response

Version and Environment

1. alphaTab version: 1.8.1
2. Platform: Android (Kotlin)
3. Devices: Android 14/16 tablet and phone

Platform

Android (Native)

Anything else?

In theory, this memory leak could eventually lead to an OutOfMemory crash, so it might be the root cause of issue #1959, but I did not push it that far in my tests.
I am currently testing a fix and can provide my version of the patch next week if needed.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions