I have software that I am working on that uses JavaFx MediaPlayers and MediaViews to create a UI. For this to work the way we want we are reusing the MediaPlayers (after keeping them stored in a static class's hashMap) and then we place the MediaPlayer in new MediaViews when needed. When the MediaView is done we set it to null and move on, but this has lead to a memory leak where the number of players will stay constant but the mediaViews will increase. I made a minimal working version of this code so you can see the memory go up and up without collecting any mediaViews. It seems like the getOnError or the Error property from the MediaPlayer is holding onto an old reference of the MediaView. I would like to remove this, but it seems like you have to dispose of a mediaPlayer if you want to clean up all of it's memory, but I would like to save the Player and delete the View.
Here is some code that recreates the issue. Just hit the stop button a few times which will remove the old mediaView and add a new one, but none ever get cleaned up.
package JavaFx;
import java.io.File;
import java.net.URL;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
public class FxMediaExample1 extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
public MediaView mediaView;
public Scene scene;
public VBox root;
@Override
public void start(Stage stage)
{
// Locate the media content in the CLASSPATH
// Create a Media
File file = new File("file:///C:/Users/Samuel%20Johnston/Downloads/cf86c6a4-271f-4dcb-bb11-fc30f5eb6b45_web.mp4");
if (file.exists()) {
System.out.println("Boobs");
} else {
System.out.println("poop");
}
Media media = new Media("file:///C:/Users/Samuel%20Johnston/Downloads/cf86c6a4-271f-4dcb-bb11-fc30f5eb6b45_web.mp4");
media.setOnError(() -> {
System.out.println("WHAT THE WHAT, " + media.getError().toString());
System.out.println("WHAT THE WHAT, " + media.getError().getMessage());
System.out.println("WHAT THE WHAT, " + media.getError().getStackTrace().toString());
System.out.println("WHAT THE WHAT, " + media.getError().getLocalizedMessage());
});
// Create a Media Player
final MediaPlayer player = new MediaPlayer(media);
player.setOnError(() -> {
System.out.println("WHY THE WHY, " + player.getError().toString());
System.out.println("WHY THE WHY, " + player.getError().getMessage());
System.out.println("WHY THE WHY, " + player.getError().getStackTrace().toString());
System.out.println("WHY THE WHY, " + player.getError().getLocalizedMessage());
});
// Automatically begin the playback
player.setAutoPlay(true);
// Create a 400X300 MediaView
mediaView = new MediaView(player);
mediaView.setFitWidth(700);
mediaView.setFitHeight(700);
mediaView.setSmooth(true);
// Create the Buttons
Button playButton = new Button("Play");
Button stopButton = new Button("Stop");
// Create the Event Handlers for the Button
playButton.setOnAction(new EventHandler <ActionEvent>()
{
public void handle(ActionEvent event)
{
if (player.getStatus() == Status.PLAYING)
{
player.stop();
player.play();
}
else
{
player.play();
}
}
});
stopButton.setOnAction(new EventHandler <ActionEvent>()
{
public void handle(ActionEvent event)
{
player.stop();
root.getChildren().remove(mediaView);
mediaView = new MediaView(player);
mediaView.setFitWidth(700);
mediaView.setFitHeight(700);
mediaView.setSmooth(true);
root.getChildren().add(mediaView);
}
});
// Create the HBox
HBox controlBox = new HBox(5, playButton, stopButton);
// Create the VBox
root = new VBox(5,mediaView,controlBox);
// Set the Style-properties of the HBox
root.setStyle("-fx-padding: 10;" +
"-fx-border-style: solid inside;" +
"-fx-border-width: 2;" +
"-fx-border-insets: 5;" +
"-fx-border-radius: 5;" +
"-fx-border-color: blue;");
// Create the Scene
scene = new Scene(root);
// Add the scene to the Stage
stage.setScene(scene);
// Set the title of the Stage
stage.setTitle("A simple Media Example");
// Display the Stage
stage.show();
}
}