我需要关闭音频剪辑吗?

时间:2010-05-08 04:57:36

标签: java audio memory-leaks

有一个处理实时数据的应用程序,并且当某个事件发生时应该发出蜂鸣声。触发事件可以每秒发生多次,并且如果在另一个事件触发时蜂鸣声已经播放,则代码应该忽略它(而不是中断当前的蜂鸣声并开始新的蜂鸣声)。这是基本代码:

Clip clickClip

public void prepareProcess() {
    super.prepareProcess();

    clickClip = null;

    try {
        clipFile = new File("C:/WINDOWS/Media/CHIMES.wav");
        ais = AudioSystem.getAudioInputStream(clipFile);
        clickClip = AudioSystem.getClip();
        clickClip.open(ais);

        fileIsLoaded = true;

    } catch (Exception ex) {
        clickClip = null;
        fileIsLoaded = false;
    }
}

public void playSound() {

    if (fileIsLoaded) {

        if ((clickClip==null) || (!clickClip.isRunning())) {

            try {
                clickClip.setFramePosition(0);
                clickClip.start();
            } catch (Exception ex) {
                System.out.println("Cannot play click noise");
                ex.printStackTrace();
            }
        }
    }

prepareProcess方法在开始时运行一次,每次发生触发事件时都会调用pl​​aySound方法。我的问题是:我需要关闭clickClip对象吗?我知道我可以添加一个actionListener来监视一个Stop事件,但由于事件经常发生,我担心额外的处理会减慢实时数据的收集速度。

代码似乎运行良好,但我担心的是内存泄漏。上面的代码基于我在搜索网络时发现的示例,但该示例使用了actionListener来专门关闭Clip“以消除在未实现stop方法时可能发生的内存泄漏”。我的程序打算运行几个小时,因此任何内存泄漏都会导致问题。

我会说实话:我不知道如何验证我是否遇到问题。我正在使用Netbeans,运行内存分析器只是给了我一大堆我不知道如何阅读的内容。这应该是该计划的简单部分,我花了几个小时。任何帮助将不胜感激!

迈克尔

2 个答案:

答案 0 :(得分:5)

是的,关闭是必要的

  myClip.addLineListener(new LineListener() {
    public void update(LineEvent myLineEvent) {
      if (myLineEvent.getType() == LineEvent.Type.STOP)
        myClip.close();
    }
  });

  if (!myClip.isRunning())
    myClip.close();

在我的应用程序中(在util.concurrent出现之前编写),这是剪辑关闭机制。

  public static final Vector<Clip> vector = new Vector<Clip>();
  static final int vector_size = 5;

  // typically called before calling play()
  static synchronized void consolidate() {
    while (vector_size < vector.size()) {
      Clip myClip = vector.get(0);
      if (myClip.isRunning())
        break;
      myClip.close();
      vector.remove(0);
    }
    if (vector_size * 2 < vector.size())
      System.out.println("warning: audio consolidation lagging");
  }

  public static void play(final File myFile) {
    try {
      AudioInputStream myAudioInputStream = AudioSystem.getAudioInputStream(myFile);
      final Clip myClip = AudioSystem.getClip();
      vector.add(myClip);
      myClip.open(myAudioInputStream);
      myClip.start();
    } catch (Exception myException) {
      myException.printStackTrace();
    }
  }

正如其中一条评论所暗示的那样,它可能会延迟播放新剪辑,但我不记得因为几毫秒的延迟在我的应用程序中并不重要。

答案 1 :(得分:0)

Java中的内存泄漏与即使在其使用寿命结束后仍被引用的对象有关。在许多情况下,这将是由于重复制作50个对象之类的东西,但后来只消除了对其中49个对象的引用。

在你的代码中似乎没有这样的东西。由于prepareProcess()只运行一次,因此不是很可疑。留下playSound(),它根本不包含任何对象实例化,更不用说错误的引用消除循环了。

需要注意的是,我不确定你的声音剪辑对象幕后发生了什么,并且很难检查,因为majuscule-C Clip只是一个界面。但是,除非您使用第三方代码,否则我会非常惊讶地发现泄漏。

长话短说,我不会担心它,除非你真的看到像OutOfMemoryError这样的东西。