Skip to content

fix: give AudioTrackSource a dispose() to release its native reference - #287

Merged
devopvoid merged 1 commit into
mainfrom
fix/audio-track-source-native-leak
Sep 15, 2026
Merged

devopvoid merged 1 commit into
mainfrom
fix/audio-track-source-native-leak

Conversation

@devopvoid

Copy link
Copy Markdown
Owner

Summary

  • PeerConnectionFactory.createAudioSource() wraps a ref-counted native AudioSourceInterface in a Java AudioTrackSource, following the same JavaFactories::create(env, ptr.release()) pattern used for AudioTrack/VideoTrack/MediaStream/etc. — but unlike those, AudioTrackSource had no dispose()/release() at all, so the one native reference handed to Java could never be released from the Java side.
  • Every call to createAudioSource() leaked one native audio source reference for the life of the process, independent of whether the resulting track, peer connection, or factory were disposed.
  • Adds a dispose() native method to AudioTrackSource (mirroring JNI_MediaStreamTrack.cpp's pattern: Release() the underlying AudioSourceInterface, log a warning if it wasn't the last ref, and null out the handle), with a matching JNI_AudioTrackSource.h/.cpp pair.
  • Updates webrtc-examples (PeerConnectionExample, PeerConnectionManager) and the get-started.md guide's cleanup snippet to dispose the audio source, since they now demonstrate a real API requirement.

Fixes #239 (confirms the leak GPT flagged in the issue's discussion).

Test plan

  • mvn -pl webrtc test — 150/150 pass, no regressions
  • New regression tests in MediaSourceTests covering dispose() both standalone and after the owning track is disposed
  • mvn -pl webrtc test -Pjni-check on the affected test classes — no FATAL ERROR in native method, only the pre-existing harmless exception-check warnings

PeerConnectionFactory.createAudioSource() returns a Java object wrapping
a ref-counted native AudioSourceInterface, but AudioTrackSource (unlike
every other ref-counted wrapper in the API) exposed no dispose()/release(),
so the one reference handed to Java could never be dropped. Every call to
createAudioSource() leaked the native audio source for the life of the
process, regardless of how the resulting track and peer connection were
torn down.
@devopvoid devopvoid mentioned this pull request Sep 15, 2026
@devopvoid
devopvoid merged commit 85e82a3 into main Sep 15, 2026
11 checks passed
@devopvoid
devopvoid deleted the fix/audio-track-source-native-leak branch September 15, 2026 21:21
SendableMetatype added a commit to EduGeyser/webrtc-java that referenced this pull request Sep 25, 2026
Brings in upstream 0.17.0 and 0.18.0 and the fixes after them: JNI
reference and thread safety fixes (devopvoid#283), field trials on
PeerConnectionFactory (devopvoid#284), CustomAudioSource and CustomVideoSource
synchronization (devopvoid#285, devopvoid#286), AudioTrackSource.dispose() (devopvoid#287),
device-captured audio kept out of sink-fed senders (devopvoid#289), and Map
method IDs taken from the interface (devopvoid#290).

Fork-side adaptations:
- The audio module proxy and the capture natives are media code: they
  are compiled out of the data channels variant, and
  ProxyAudioDeviceModule.cpp is excluded from its source list.
- The data channels variant passes the field trials through the
  factory's Environment, as CreatePeerConnectionFactory does.
- The Maven poms stay deleted; upstream's jni-check profile becomes the
  Gradle property -Pjni-check.
- The new tests that need audio or video carry the media tag.
- The changelog keeps upstream's 0.17.0 and 0.18.0 sections in date
  order next to the fork's 0.17.0-sm.1 section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Suspected memory leak

1 participant