我的应用程序在启动时加载了一堆音频剪辑.它用于java.applet.Applet.newAudioClip(URL audioFileURL)加载文件,这些文件位于同一文件夹中.我可以看到这个函数基本上是一个获取JavaSoundAudioClip对象的包装器
直到昨天,我用JDK 7编译JAR并使用JRE版本7更新45启动它.然后我更新到版本8更新31.
现在,每个音频的加载比以前多十倍(每个0.2秒,现在它在2到3秒之间)
在不同的硬件配置上发生了相同的行为.操作系统是64位Windows 7,Java 7和8运行时环境都是32位.
在挖掘更深层次的调试,我发现,放慢了大部分的方法是AudioSystem.getAudioInputStream,AudioSystem.isLineSupported,AudioSystem.getLine
不应该涉及音频格式:我尝试了OGG和WAV,结果相同.
两个JVM的设置都是相同的
编辑:即使我无法在ad-hoc的小程序中重现问题.Java 8确实较慢,但只有10%的因素.我的应用程序必须有一些特别的东西,而我正在使用的库与音频系统和/或其流有冲突.我一发现就会更新.
我正在使用jlGui的BasicPlayer 播放音频文件(它基于Javasound).该文件位于Samba共享中,我正在使用Jcifs来访问它.它给了我一个InputStream.
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication( ... );
SmbFile f = new SmbFile( ... );
SmbFileInputStream audioIn = new SmbFileInputStream(f);
int bufSize = 8096;//should I use f.length() here?
audioBIS = new BufferedInputStream(audioIn, bufSize);
audioBIS.mark(f.length());
//call BasicPlayer
play(audioBIS);
Run Code Online (Sandbox Code Playgroud)
我需要能够将指针放在文件中的任何位置,就像任何普通玩家一样.我能想到的唯一解决方案是BufferedInputStream每次我需要重新定位指针时使用a 和mark/reset/skip的组合.一旦我打开文件并获取Stream,我就会调用该mark()方法,以便后续reset()将在开始时重新定位我.然后,skip()我可以去我想要的地方.
audioBIS.reset();
audioBIS.skip(newBytePosition);
Run Code Online (Sandbox Code Playgroud)
我的问题是只有当我指定一个足够大的缓冲区来包含整个文件时,skip()调用才能正常工作.
有没有更有效的方法来做到这一点?