为什么JavaFX媒体播放器崩溃?

时间:2017-12-15 15:33:06

标签: java javafx garbage-collection

我正确安装了Java 8,它是oracle版本(不是OpenJDK)。我的IDE是Eclipse。当我在JavaFX项目中运行以下代码时,

import java.io.File;
import javafx.embed.swing.JFXPanel;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class TestPlayer {
    static JFXPanel fxPanel =new JFXPanel();
    private Media song;
    private MediaPlayer mediaPlayer ;
    public TestPlayer(String filePath) {
        song=new Media(new File(filePath).toURI().toString());
        mediaPlayer = new MediaPlayer(song);
    }

    public void play() {
        this.mediaPlayer.play();
    }
     public static void main(String[] args) {
         new TestPlayer("song\\1.mp3").play();
     }
}

mediaPlayer只能播放几秒钟的歌曲,然后没有声音,也没有异常抛出。

然后我从

改变了第8行
private Media song;

private static Media song;

修改后的代码成功运行。

我想知道问题解决的原因。以下两个屏幕截图是在Eclipse的调试模式下进行的。

修改前: enter image description here

修改后: after modification

区别在于" JFXMedia Player EventQueueThread"。

1 个答案:

答案 0 :(得分:1)

您正在看到媒体播放器线程的垃圾收集问题 - JFXMedia Player EventQueueThread。我使用VisualVM来监控线程和GC。

您的代码启动MediaPlayer并返回,使实例引用符合GC条件。在这里,我在发射后几秒钟(6:44:57)强制使用GC:

enter image description here

同时JFXMedia Player EventQueueThread停止了:

enter image description here

通过创建MediaMediaPlayer static,您将它们绑定到类加载器而不是类实例,因此它们不符合收集条件。通常,在使用JavaFX类时,应该将Application子类化。该类的JavaDoc声明:

  

<强>线程

     

JavaFX创建一个用于运行应用程序启动的应用程序线程   方法,处理输入事件和运行动画时间轴。

     

Java启动程序加载并初始化指定的Application   JavaFX应用程序线程上的类。如果没有主要方法   Application类,或者main方法调用   然后是Application.launch(),然后是Application的一个实例   在JavaFX应用程序线程上构造。

以这种方式运行代码时,GC无法收集JFXMedia Player EventQueueThread。我再次发起了GC(7:19:04)

enter image description here

现在线程还活着:

enter image description here

请注意,main线程也与JavaFX-Launcher一起存在。

对于真正的深度分析,您必须检查堆转储,但希望这种洞察力足以解决问题的范围。