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

为什么JavaFX媒体播放器会崩溃?,java,javafx,garbage-collection,Java,Javafx,Garbage Collection,我已经正确安装了Java8,它是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 fxPa

我已经正确安装了Java8,它是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;

修改后的代码运行成功

虽然问题解决了,但我想知道原因。以下两个屏幕截图是在Eclipse的调试模式下拍摄的

修改前:

修改后:


区别在于“JFXMedia Player EventQueueThread”。

您看到媒体播放器线程的垃圾收集问题-
JFXMedia Player EventQueueThread
。Iv'e用于监视线程和GC

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

同时,
JFXMedia Player事件队列线程
停止:

通过使
媒体
媒体播放器
静态
将它们绑定到类加载器而不是类实例,因此它们不符合收集条件。通常,在使用JavaFX类时,应该将应用程序子类化为
Application
。该类的JavaDoc声明:

线程化

JavaFX为运行应用程序启动创建应用程序线程 方法,处理输入事件,并运行动画时间线

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

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

现在线程仍然处于活动状态:

请注意,
main
线程也与
JavaFX启动器一起存在


要进行真正深入的分析,您必须检查堆转储,但希望这种洞察力足以解决问题。

添加
静态
不太可能是正确的解决方案。请你能发布它崩溃时的堆栈跟踪吗?当你添加静态时,你创建了一个实例吗?!在这里添加
static
所产生的区别是,您可以防止
媒体
实例超出范围。我猜,实际上播放媒体的线程只保留了对它的弱引用。在实际应用程序中,这显然不是问题。可能是垃圾收集问题。如果任何JavaFX类在没有子类的情况下都能正常工作,我会感到惊讶。
private static Media song;