繁体   English   中英

用java播放声音时内存泄漏

[英]Memory leak while playing sounds with java

这是我播放声音的代码:

public class Sound {
    public static void playSound(String path)
    {
      try 
      {
           Clip clip = AudioSystem.getClip();
           AudioInputStream inputStream = AudioSystem.getAudioInputStream(new File(path));
           clip.open(inputStream);
           inputStream.close();
           clip.start(); 
        } catch (Exception e) {
           e.printStackTrace();
        }               
    }
}

如果我调用 Sound.playSound("xxx.wav"); 很多次我看到我的 ram 根据任务管理器开始急剧上升。 我该如何清理它?

尝试关闭方法。 来自 JavaDOC:

void close() 关闭该行,表示该行正在使用的任何系统资源都可以释放。 如果此操作成功,则该行被标记为已关闭,并且会向该行的侦听器分派 CLOSE 事件。

您编写 Clip 的方式(包括加载和播放)表明 SourceDataLine 会更有效。 在播放剪辑的同时加载剪辑会产生大量不必要的延迟。 在文件完全加载到 RAM 之前,剪辑不会开始播放,而 SourceDataLine 将立即开始(一旦开始接收文件数据)。

剪辑应该通过 open() 加载一次。 打开后,数据位于 RAM 中,随时可用。 剪辑旨在以尽可能低的延迟进行多次播放。 但是,只有将加载与播放分开,并且只是在已加载的剪辑上调用播放,才能实现这种低延迟。

内存分配的增加可能是由于您的所有剪辑继续重新加载到 RAM 中。 (每次调用都会在 RAM 中创建一个额外的实例,音频文件并不便宜。)如果您重放一个剪辑,只需加载一次,然后通过多次 start() 调用重复使用它。

使用 SourceDataLine 是另一种选择。 它不会将整个声音文件加载到 RAM 中,而是从文件位置流式传输它。 但一定要在完成后关闭它,因为未关闭的数据行或文件流可能是内存泄漏的另一个来源。

首先,正如其他人所建议的那样 - 在Clip clip上使用close()方法。 也关闭inputStream (就像您现在所做的那样)。

另一件事是 Java 自己管理内存(通过 JVM - Java 虚拟机)。 例如,对象在它们变得过时时被清除(即超出范围,没有引用)。 它与必须分配和释放内存的 C++ 不同。

但是在 Java 中,“解除分配”是使用Garbage Collector (网上有很多参考资料)。 GC 是由 JVM 调用的,很难准确判断何时。

所以我们在这里看到的是 Java 将一些资源加载到内存中(以对象方式处理它)。 它们中的每一个都耗尽了您的系统内存。 使用后不会立即清除内存。 一旦 JVM 调用 GC,它将被清除。 这并不意味着您有内存泄漏。

两个提示:

  • JVM 会在系统内存不足的情况下调用 GC,因此您不必担心没有资源(除非您同时使用大量资源)。
  • 您可以手动“要求”GC 使用 Java 代码执行操作: System.gc()但不能保证它会立即执行。

编辑:要确认这一点,请尝试手动调用 gc (System.gc()) 并查看它是否释放内存,但您不应在最终解决方案中使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM