vlc-android-sdk
vlc-android-sdk copied to clipboard
Memory Leak in MediaPlayer.Event and VLCObject.EventRunnable
When implementing my own event listener for a media player, I found that the heap displays a massive amount of MediaPlayer.Events and VLCObject.EventRunnables. In some cases I see 3,000-8,000 instances of these events or event runnables.
There are two places I see this happening:
- At the inner class where the EventRunnable is being created and posted with the event handler.
- And where the event is dispatched via the weak native event. I don't know how this is being handled in the native library, but it seems something is amiss.
I'm using both vlc-android 2.0.6 and 2.1.2.
/* JNI */
@SuppressWarnings("unused") /* Used from JNI */
private long mInstance = 0;
private synchronized void dispatchEventFromNative(int eventType, long arg1, float arg2) {
if (isReleased())
return;
final T event = onEventNative(eventType, arg1, arg2);
class EventRunnable implements Runnable {
private final VLCEvent.Listener<T> listener;
private final T event;
private EventRunnable(VLCEvent.Listener<T> listener, T event) {
this.listener = listener;
this.event = event;
}
@Override
public void run() {
listener.onEvent(event);
}
}
if (event != null && mEventListener != null && mHandler != null) {
mHandler.post( new EventRunnable(mEventListener, event));
}
}
@SuppressWarnings("unchecked,unused") /* Used from JNI */
private static void dispatchEventFromWeakNative(Object weak, int eventType, long arg1, float arg2) {
VLCObject obj = ((WeakReference<VLCObject>)weak).get();
if (obj != null) {
obj.dispatchEventFromNative(eventType, arg1, arg2);
obj.release();
}
}
- My PlayerListener:
public class PlayerListener implements MediaPlayer.EventListener {
private final static String TAG = PlayerListener.class.getSimpleName();
private static WeakReference<Player> mOwner;
PlayerListener(Player owner) {
mOwner = new WeakReference<>(owner);
}
@Override
public void onEvent(MediaPlayer.Event event) {
Player player = mOwner.get();
if(player != null) {
switch (event.type) {
case MediaPlayer.Event.EndReached:
Log.i(TAG, "EndReached------------------");
break;
case MediaPlayer.Event.Playing:
Log.i(TAG, "Playing------------------");
break;
case MediaPlayer.Event.Paused:
Log.i(TAG, "Paused------------------");
break;
case MediaPlayer.Event.Stopped:
Log.i(TAG, "Stopped------------------");
break;
case MediaPlayer.Event.PositionChanged:
//Log.i(TAG, "Position Changed------------------: " + player.getMediaPosition());
break;
case MediaPlayer.Event.MediaChanged:
Log.i(TAG, "MediaChanged------------------");
break;
case MediaPlayer.Event.Vout:
Log.i(TAG, "Vout------------------");
break;
case MediaPlayer.Event.ESAdded:
Log.i(TAG, "ESAdded------------------");
break;
case MediaPlayer.Event.ESDeleted:
Log.i(TAG, "ESAdded------------------");
break;
case MediaPlayer.Event.Opening:
Log.i(TAG, "Opening------------------");
break;
case MediaPlayer.Event.Buffering:
Log.i(TAG, "Buffering------------------");
break;
case MediaPlayer.Event.TimeChanged:
// Log.i(TAG, "TimeChanged------------------: " + player.actualPlaybackLength);
break;
case MediaPlayer.Event.SeekableChanged:
Log.i(TAG, "SeekableChanged------------------");
break;
case MediaPlayer.Event.EncounteredError:
Log.e(TAG, "EncounteredError------------------");
break;
case MediaPlayer.Event.PausableChanged:
Log.i(TAG, "PausableChanged------------------");
break;
default:
break;
}
} else {
Log.i(TAG, "Player class is null in Player Listener.");
}
}
}