问题
I'm trying to play a sound in a Java application but the application never actually terminates because the PulseAudio Eventloop thread is left running even after trying to close the Clip instance used for playing the sound:
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
final class AudioClipTest {
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
try (AudioInputStream instream = AudioSystem.getAudioInputStream(new File("resources/test-sound.wav"))){
final AudioFormat format = instream.getFormat();
final Clip clip = (Clip) AudioSystem.getLine(new DataLine.Info(Clip.class, format));
clip.addLineListener(new LineListener() {
@Override
public void update(final LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
System.out.println("Finished playing audio.");
event.getLine().close();
// FIXME: This line is never reached on Linux with
// PulseAudio
System.out.println("Closed audio data line.");
}
}
});
clip.open(instream);
clip.start();
}
}
}
On my Linux machine†, the above main method plays the relevant sound, prints
Finished playing audio.
and then hangs, while on a Windows‡ machine it prints
Finished playing audio.
Closed audio data line.
and exits properly.
The actual Clip
implementation used on the Linux machine is org.classpath.icedtea.pulseaudio.PulseAudioClip
whereas on Windows it is com.sun.media.sound.DirectAudioDevice.DirectClip
; What is going on here? — What is PulseAudioClip.close()
doing which isn't returning?
†Distribution: Linux Mint 18.1; Kernel: 4.4.0-92-generic x86_64; OpenJDK: 8u131-b11-2ubuntu1.16.04.3; PulseAudio: 1:8.0-ubuntu3.3
‡Distribution: Windows 10 Pro; Version: 1703; OS Build: 15063.540 x64; Oracle JDK: 1.8.0_144-b01; DirectX: version 12
回答1:
One possible way to work around this issue is to use the Alsa (userspace) API for playing audio using Java. The alsa userspace API will redirect to PulseAudio (or another API/mixer) so you should still get correct audio.
Edit $JAVA_HOME/jre/lib/sound.properties
and comment out everything related to org.classpath.icedtea.pulseaudio
and add this:
javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider
Also, please file a bug against your distribution's openjdk package. The PulseAudio/Java bindings have been unsupported for years now and should be removed.
来源:https://stackoverflow.com/questions/45847635/java-audio-clip-cannot-be-closed-when-using-linux-pulseaudio