JDK-8093636 : [media] Native memory leaking until nio.Buffers are GC'ed
  • Type: Bug
  • Component: javafx
  • Sub-Component: media
  • Affected Version: 7u55,8u5
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2014-05-07
  • Updated: 2018-02-01
  • Resolved: 2014-05-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8u20Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Sub Tasks
JDK-8094501 :  
Description
After a number of opening/disposing very long media files we may run out of the native memory while the Java heap is almost free. That leads to inability to open a media until the first full GC. No crashes observed.

When the moov table is parsed the qtdemuxer asks to read that table in a single block. For 12hr mp4 that requires about 50Mb. The stream java source allocates direct ByteBuffer when asked for readBlock(). For reading the moov table the direct ByteBuffer of 50Mb is allocated. The problem is that this native memory could be released only when the instance of this ByteBuffer is garbage collected and thus native memory may leak even if the MediaPlayer.dispose() is called when closing media.
Since there is no API for controlling media source stream operations the only workaround is to call System.gc() after MediaPlayer.dispose(), though no guarantees here of course. 
Comments
Fix Summary Template - Fix for Release : 7 (2.2.x) - Risk Analysis : Low - Testing : The testcase is attached. The long enough video file is needed (I used 12hr mp4) to reproduce the problem. It should be specified as an argument. It is better to run the case on jre x32 with -Xmx1024M to leave less native memory for the process. (The large mp4 file is stored locally on my laptop and I could share it via FTP if needed) - JavaFX Impact : YES
08-07-2014

Testcase
08-07-2014

Changeset: http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/c4fedef42f45
20-05-2014

Approved
20-05-2014

Approved.
12-05-2014

I thought about this case, but my fix seemed to me safer and easier. With manual buffer management you also need to implement reference tracking to release native memory if the stream was just GCed without calling closeConnection(). This is already implemented in the DirectByteBuffer and reusing this functionality would be less error prone.
12-05-2014

Did you try to manage native memory for ByteBuffer yourself? You can use JNI NewDirectByteBuffer to allocate buffer with preallocated native memory and then free it when we no longer need it.
08-05-2014

The problem is resolved by casting ByteBuffer to DirectBuffer and calling getCleaner().clean() on closeConnection(). Webrev: http://cr.openjdk.java.net/~anashaty/RT-37012/webrev.00/
08-05-2014

Two possible solutions here: 1. Change the moov table parsing algorithm in the qtdemuxer so it may request the stream with a smaller chunks 2. Allocate Java heap bytebuffer when the requested size is larger than some threshold (though the strait changing 'direct' flag when creating ByteBuffer led to crash for me)
07-05-2014