JDK-7095006 : getAudioInputStream has changed in Java 7 (mark/reset not supported for wav files)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.sound
  • Affected Version: 7,8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_7
  • CPU: x86
  • Submitted: 2011-09-26
  • Updated: 2019-04-29
  • Resolved: 2019-04-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdResolved
Description
FULL PRODUCT VERSION :
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
Calls to javax.sound.sampled.AudioSystem.getAudioInputStream which worked in Java 6 fail in Java 7 because the underlying stream does not support Mark/Reset. This is not backwards compatible, and should be flagged in the release notes to Java 7. If it is flagged, I apologise in advance - I must have missed it. Anyway, I can see no reason for insisting that audio streams have to be markable - all the program does is make a short clip.

I hope I have chosen the correct subtopic - there didn't seem to be one for javax.sound.

REGRESSION.  Last worked in version 6u26

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the program (you will need a short audio file in the "Sounds" directory) under both Java 6 and 7.

I have been using NetBeans 6 to generate the JAR file. Netbeans 7 gives the same result.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A blank panel.
ACTUAL -
Under Java 6 it shows a blank panel. Under Java 7 there is a program-generated error message showing the problem.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

package com.ptoye.Metronome1;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
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.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JOptionPane;

/**
 *
 * @author PToye
 */
public class jfMetronome extends javax.swing.JFrame {

    /**
     * Number of positions of the metronome display. Must be odd.
     */
  
    private Clip clickClip = null;

    /** Creates new form jfMetronome */
    public jfMetronome() {
        InputStream clickInputStream = null;
        File clickSound = null;

        initComponents();

        Class thisClass = this.getClass();
        URL clickURL = thisClass.getResource("Sounds/clickmono.wav");
        URI clickURI = null;
        try {
            clickURI = clickURL.toURI();
        } catch (URISyntaxException ex) {
            Logger.getLogger(jfMetronome.class.getName()).log(Level.SEVERE, "URI Syntax exception", ex);
        }
        String clickScheme = clickURI.getScheme();
        if (clickScheme.equals("file")) {
            try {
                clickSound = new File(clickURI);
                clickInputStream = new FileInputStream(clickSound);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(pnlMnome, "Cannot create file from " + clickURI);
            }

        } else if (clickScheme.equals("jar")) {
            String clickJarFileRef = clickURI.getSchemeSpecificPart();
            int shriekPos = clickJarFileRef.indexOf("!");
            if (shriekPos < 0) {
                JOptionPane.showMessageDialog(pnlMnome, "Cannot parse Jar file reference: no \"!\"");
            } else {
                String jarFileName = clickJarFileRef.substring(0, shriekPos);
                String clickFileName = clickJarFileRef.substring(shriekPos + 1);
                if (jarFileName.startsWith("file:")) {
                    jarFileName=jarFileName.substring(5);
                }
                if (clickFileName.startsWith("/")) {
                    clickFileName=clickFileName.substring(1);
                }
                JarFile jf = null;
                try {
                    jf = new JarFile(jarFileName);
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(pnlMnome, "Cannot get JAR file:" + jarFileName);
                }

                JarEntry je = jf.getJarEntry(clickFileName);
                if (je != null) {
                    try {
                        clickInputStream =   jf.getInputStream(je);
//                        JOptionPane.showMessageDialog(pnlMnome, "inputStream="+clickInputStream);
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(pnlMnome, "Cannot create input stream:" + je);
                    } catch (Exception e) {
                        JOptionPane.showMessageDialog(pnlMnome, "Exception in input stream:"+e);
                    }
                } else {
                    JOptionPane.showMessageDialog(pnlMnome, "Cannot find file in JAR: " + clickFileName);
                }

            }

        }
        if (clickInputStream == null) {
            JOptionPane.showMessageDialog(pnlMnome, "Cannot find click file");
            System.exit(3);
        } else {
  //          JOptionPane.showMessageDialog(pnlMnome, "Click file found OK: mark/reset="+clickInputStream.markSupported());
            AudioInputStream audioInputStream = null;
            try {
                audioInputStream = AudioSystem.getAudioInputStream(clickInputStream);
            } catch (UnsupportedAudioFileException ex) {
                JOptionPane.showMessageDialog(pnlMnome, "Audio file exception "+ ex);
                System.exit(1);
            } catch (IOException ex) {
// ****** THIS IS THE EXCEPTION!!!! ******
                JOptionPane.showMessageDialog(pnlMnome, "IO exception " + ex);
                System.exit(2);

            }
            AudioFormat audioFormat = audioInputStream.getFormat();
            DataLine.Info dataLineInfo = new DataLine.Info(
                    Clip.class, audioFormat);
            try {
                clickClip = (Clip) AudioSystem.getLine(dataLineInfo);
            } catch (LineUnavailableException ex) {
//            Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
//                System.exit(1);
            }
            try {
                clickClip.open(audioInputStream);
            } catch (LineUnavailableException ex) {
                JOptionPane.showMessageDialog(pnlMnome, "Click line unavailable:"+audioInputStream);
//            Logger.getLogger(TrySound.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(pnlMnome, "IO exception opening click stream"+audioInputStream);
//            Logger.getLogger(TrySound.class.getName()).log(Level.SEVERE, null, ex);
            }
        }


    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        pnlMnome = new javax.swing.JPanel();

        FormListener formListener = new FormListener();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Metronome �� Peter Toye");
        addWindowListener(formListener);
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.LINE_AXIS));

        pnlMnome.setBackground(new java.awt.Color(0, 0, 0));
        pnlMnome.setPreferredSize(new java.awt.Dimension(800, 600));
        pnlMnome.setLayout(null);
        getContentPane().add(pnlMnome);

        pack();
    }

    // Code for dispatching events from components to event handlers.

    private class FormListener implements java.awt.event.WindowListener {
        FormListener() {}
        public void windowActivated(java.awt.event.WindowEvent evt) {
        }

        public void windowClosed(java.awt.event.WindowEvent evt) {
        }

        public void windowClosing(java.awt.event.WindowEvent evt) {
        }

        public void windowDeactivated(java.awt.event.WindowEvent evt) {
        }

        public void windowDeiconified(java.awt.event.WindowEvent evt) {
        }

        public void windowIconified(java.awt.event.WindowEvent evt) {
        }

        public void windowOpened(java.awt.event.WindowEvent evt) {
            if (evt.getSource() == jfMetronome.this) {
                jfMetronome.this.formWindowOpened(evt);
            }
        }
    }// </editor-fold>

    private void formWindowOpened(java.awt.event.WindowEvent evt) {
        if (!pnlMnome.requestFocusInWindow()) {
            JOptionPane.showMessageDialog(this, "Cannot get focus for panel");
        }
    }

 

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new jfMetronome().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JPanel pnlMnome;
    // End of variables declaration
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Have not found one yet.

Comments
https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/sound/sampled/AudioSystem.html#getAudioInputStream(java.io.InputStream) ===== Obtains an audio input stream from the provided input stream. The stream must point to valid audio file data. The implementation of this method may require multiple parsers to examine the stream to determine whether they support it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and reset the stream's read pointer to its original position. If the input stream does not support these operation, this method may fail with an IOException. =====
29-04-2019

not a regression for 8 and 9
12-12-2014

- this is an issue reported against 7(7u), - there are now affected version 9 filed for this issue - 7u issues are transferred to Sustaining Nevertheless if someone have a report against 9 - please reopen and add affectedVersion 9 or 7u specific escalations might be reopen to Sustaining
10-08-2014

- this is an issue reported against 7(7u), - there are now affected version 9 filed for this issue - 7u issues are transferred to Sustaining Nevertheless if someone have a report against 9 - please reopen and add affectedVersion 9 or 7u specific escalations might be reopen to Sustaining
10-08-2014

EVALUATION The issue is similar to CR 6408764 getAudioInputStream needs input stream to support merk/reset, otherwise it can try only the 1st file reader provider in the file reader provider list. in jdk6 wav reader was 1st in the file reader list so the code worked. (if classpath contains some additional file readers or input file is .au/.snd or .aif, the example fails with jdk6 too) in jdk7 new readers were added and wav reader now is not the 1st reader in the list.
07-10-2011