do I need to close an audio Clip?

2019-03-02 20:05发布

问题:

have an application that processes real-time data and is supposed to beep when a certain event occurs. The triggering event can occur multiple times per second, and if the beep is already playing when another event triggers the code is just supposed to ignore it (as opposed to interrupting the current beep and starting a new one). Here is the basic code:

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();
            }
        }
    }

The prepareProcess method gets run once in the beginning, and the playSound method is called every time a triggering event occurs. My question is: do I need to close the clickClip object? I know I could add an actionListener to monitor for a Stop event, but since the event occurs so frequently I'm worried the extra processing is going to slow down the real-time data collection.

The code seems to run fine, but my worry is memory leaks. The code above is based on an example I found while searching the net, but the example used an actionListener to close the Clip specifically "to eliminate memory leaks that would occur when the stop method wasn't implemented". My program is intended to run for hours so any memory leaks I have will cause problems.

I'll be honest: I have no idea how to verify whether or not I've got a problem. I'm using Netbeans, and running the memory profiler just gave me a huge list of things that I don't know how to read. This is supposed to be the simple part of the program, and I'm spending hours on it. Any help would be greatly appreciated!

Michael

回答1:

yes, closing is necessary

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

or by

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

In my application (written before the advent of util.concurrent), this is the clip closing mechanism.

  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();
    }
  }

As one of the comments suggest, it may delay the playback of new clips, but I cannot remember as a few ms delay were not important in my application.



回答2:

Memory leaks in Java have to do with objects that are still being referenced even after their useful lives have ended. In many cases, this will be due to something like repeatedly making 50 objects but only eliminating references to 49 of them later on.

Nothing like that seems to be going on in your code. Since prepareProcess() only runs once, it's not highly suspect. That leaves playSound(), which doesn't contain any object instantiation at all, much less a faulty reference elimination loop.

The caveat is that I'm not sure what goes on behind the scenes in your sound clip object, and it's hard to check because majuscule-C Clip is only an interface. Unless you're using third-party code, though, I'd be very surprised to find a leak there.

Long story short, I wouldn't worry about it unless and until you actually see something like an OutOfMemoryError.