在 Java 中播放音频而没有内存泄漏

Posted

技术标签:

【中文标题】在 Java 中播放音频而没有内存泄漏【英文标题】:Audio playing in Java without memory leaks 【发布时间】:2016-03-08 22:51:06 【问题描述】:

我的游戏中有一个当前系统,其中有一个 AudioPlayer 类,它包含 AudioChannels。我不断收到堆转储(我已经用 MAT 查看过)并指向:

com.sun.media.sound.DirectAudioDevice$DirectClip.open(Unknown Source)

MAT 中的泄漏如下所示:

127 instances of "com.sun.media.sound.DirectAudioDevice$DirectClip", loaded by "<system class loader>" occupy 754,011,696 (94.80%) bytes. 

Biggest instances:
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xcc5e9f18 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xce3cf970 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xdf62fc58 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xdf741840 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2b7b968 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2b7f2a0 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c80678 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c844a8 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe59e1d18 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xec186a20 - 30,427,248 (3.83%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xcc5ea388 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xcc654850 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe1502670 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2b7bdd8 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2b7f688 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c80ae8 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c84890 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe4363c68 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xeab00030 - 23,556,720 (2.96%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xcc5eb828 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xcc655cf0 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe14965f8 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe1503b10 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2b7d5c0 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c7edb8 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2c827c8 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe2cf37c8 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xe7746aa0 - 23,049,840 (2.90%) bytes. 
•com.sun.media.sound.DirectAudioDevice$DirectClip @ 0xee91fae0 - 23,049,840 (2.90%) bytes. 

我不知道这是怎么回事,因为我正在尽我所能卸载 Clip 和 AIS。

这是我用来播放音频的代码:

try 
    AudioInputStream ais = Audiosystem.getAudioInputStream(FileReader.getFile(s));
    clip = AudioSystem.getClip();
    clip.open(ais);
    loaded = true;

    FloatControl g = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
    g.setValue((float)(g.getMinimum() + ((double)(g.getMaximum() - g.getMinimum()) * volume)));

    if (loops) 
        clip.loop(Clip.LOOP_CONTINUOUSLY);
     else 
        clip.start();
    

    ais.close();
    clip.drain();
 catch (Exception e) 
    e.printStackTrace();

【问题讨论】:

【参考方案1】:

您没有关闭音频剪辑。一旦你有空并且有能力,你应该尝试关闭它们:

if (clip.isOpen()) 
    clip.close();

显然,这可能需要您做更多的工作来跟踪剪辑的生命周期,这样您就可以确保它们可以以对您的应用程序有意义的方式发布。

另见:

do I need to close an audio Clip? Java Clip (Sound / Audio) Memory Leak after closing with close()

【讨论】:

以上是关于在 Java 中播放音频而没有内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Java 在 Windows 上播放音频,但在 Ubuntu 上不播放

iOS - AudioToolbox 内存泄漏

如何在 Java 中播放 Opus 编码的音频?

如何读取我们的系统(PC 声卡或扬声器)在 java 中播放的音频流

重新编辑:音频不在真正的 ios 设备中播放,而是在 Swift2 的模拟设备中播放

读取音频文件而不播放它