我正确安装了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的调试模式下进行的。
区别在于" JFXMedia Player EventQueueThread"。
答案 0 :(得分:1)
您正在看到媒体播放器线程的垃圾收集问题 - JFXMedia Player EventQueueThread
。我使用VisualVM来监控线程和GC。
您的代码启动MediaPlayer
并返回,使实例引用符合GC条件。在这里,我在发射后几秒钟(6:44:57)强制使用GC:
同时JFXMedia Player EventQueueThread
停止了:
通过创建Media
或MediaPlayer
static
,您将它们绑定到类加载器而不是类实例,因此它们不符合收集条件。通常,在使用JavaFX类时,应该将Application
子类化。该类的JavaDoc声明:
<强>线程强>
JavaFX创建一个用于运行应用程序启动的应用程序线程 方法,处理输入事件和运行动画时间轴。
Java启动程序加载并初始化指定的Application JavaFX应用程序线程上的类。如果没有主要方法 Application类,或者main方法调用 然后是Application.launch(),然后是Application的一个实例 在JavaFX应用程序线程上构造。
以这种方式运行代码时,GC无法收集JFXMedia Player EventQueueThread
。我再次发起了GC(7:19:04)
现在线程还活着:
请注意,main
线程也与JavaFX-Launcher
一起存在。
对于真正的深度分析,您必须检查堆转储,但希望这种洞察力足以解决问题的范围。