Wednesday, 21 January 2009

JavaFX MediaPlayer Memory Leak?

I wrote an e-card using JavaFX 1.0 to celebrate the upcoming Chinese New Year. It's a typical little multimedia applet with some animation, music and sound effect - supposedly perfect for JavaFX. However, I found that the memory usage is steadily climbing even when there is no activity (animation) happening on the canvas. I refactored, double-checked, triple-checked my source code several times to make sure that there was no unnecessary object creation and to reuse objects (by changing the opacity) every time - but to no avail.

Then I did a little experiment and found out that the number-one culprit could be the javafx.scene.media.MediaPlayer. The test program has a MediaPlayer and blank canvas with two buttons - the Start button to play the media/music; and the Stop button to stop the music. The source code for this simple test is shown below.

package testjavafx;

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.ext.swing.SwingButton;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

var m=MediaPlayer {
    autoPlay: false
    repeatCount: MediaPlayer.REPEAT_FOREVER
    media: Media {
        source: "{__DIR__}bubugao.mp3"
    }
};
Stage {
    title: "Application title"
    width: 250
    height: 250
    scene: Scene {
        content: [
            MediaView {
                mediaPlayer: m
            }
            SwingButton {
                translateY:100
                text: "Start"
                action: function() {  
                    m.play();
                }
            },
            SwingButton {
                translateY: 150
                text: "Stop"
                action: function() {  
                    m.stop();
                }
            }
        ]
    }
}

Profiling the application, I found the same memory usage pattern: memory usage climbs steadily with every time the media is played (i.e. pressing the Start button). The heap graphs below are captured from NetBeans 6.5.

The notes on the first graph (on the left) are explained below:

  1. play - the Start button was pressed
  2. GC - garbage collection was forced by pressing the GC icon several times in NetBeans
  3. stop - the Stop button was pressed
  4. GC - garbage collection was forced

The notes on the second graph (on the right) are explained below:

  1. GC - garbage collection was forced by pressing the GC icon several times in NetBeans
  2. play - the Start button was pressed several times quickly
  3. stop - the Stop button was pressed
  4. GC - garbage collection was forced

The MediaPlayer also has very limited support on media formats - it does not support wave files, or MPEG-2.5 sound files... so that I couldn't use most of the sound-effect files available on the internet. So this is Sun's solution to multimedia applications?!

1 comment:

Anonymous said...

I'm a Java developer and I was amazed what handicap child Sun throw on the market. But just wait 10 years and you will see nice improvements into the 6th version.