我们可以在Java手机上使用Java Midlet在诺基亚电话(N80 / N95)上录制音频而不会导致JVM内存泄漏吗?
我想用Java Midlet在诺基亚手机上重复捕获音频片段。我目前的经验是使用Sun文档中的代码(请参阅:http://java.sun.com/javame/reference/apis/jsr135/javax/microedition/media/control/RecordControl.html),并将其包装在" while(true)"循环有效,但是应用程序缓慢消耗了手机上的所有内存,并且该程序最终引发异常,无法启动进一步的记录。
消耗的内存不是Java堆内存-我的示例程序(如下所示)显示Java内存在大约185,000字节左右大致保持静态-–但是诺基亚提供的基础支持库中存在某种内存泄漏;我相信会发生内存泄漏,因为如果我们在运行Java应用程序一段时间后尝试启动另一个(非Java)应用程序(例如Web浏览器),则手机会杀死该应用程序,并发出有关内存不足的警告。
我已经尝试了几种与Sun文档中的规范示例所采用的方法不同的方法(每次在循环中初始化所有内容,最多初始化一次,调用尽可能多的deallocate样式函数,这些并不是必须的)等等。)。没有一个似乎是成功的。下面是一个简单的示例程序,我相信它应该可以运行,但是在N80(尽管有固件更新)和N95上运行15分钟左右后崩溃。其他论坛也报告了此问题,但是那里提出的解决方案似乎不起作用(例如,请参阅:http://discussion.forum.nokia.com/forum/showthread.php?t=129876)。
import javax.microedition.media.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java.io.*; public class Standalone extends MIDlet { protected void startApp() { final Form form = new Form("Test audio recording"); final StringItem status = new StringItem("Status",""); form.append(status); final Command exit = new Command("Exit", Command.EXIT, 1); form.addCommand(exit); form.setCommandListener(new CommandListener() { public void commandAction(Command cmd, Displayable disp) { if (cmd == exit) { destroyApp(false); notifyDestroyed(); } } }); Thread t = new Thread(){ public void run() { int counter = 0; while(true) { //Code cut 'n' paste from Sun JSR135 javadocs for RecordControl: try { Player p = Manager.createPlayer("capture://audio"); p.realize(); RecordControl rc = (RecordControl)p.getControl("RecordControl"); ByteArrayOutputStream output = new ByteArrayOutputStream(); rc.setRecordStream(output); rc.startRecord(); p.start(); Thread.currentThread().sleep(5000); rc.commit(); p.close(); } catch (Exception e) { status.setText("completed "+counter+ " T="+Runtime.getRuntime().totalMemory()+ " F="+Runtime.getRuntime().freeMemory()+ ": Error: "+e); break; } counter++; status.setText("completed "+counter+ " T="+Runtime.getRuntime().totalMemory()+ " F="+Runtime.getRuntime().freeMemory()); System.gc(); //One forum post suggests this, but doesn't help this.yield(); } } }; t.start(); final Display display = Display.getDisplay(this); display.setCurrent(form); } protected void pauseApp() {} protected void destroyApp(boolean bool) {} }
解决方案
我认为我们应该提交错误报告,而不要尝试解决该问题。
N系列诺基亚设备存在已知的内存泄漏。它不是特定于Java的,而是在OS的底层。
最近,我在开发针对诺基亚N90的游戏时,遇到了类似的问题。我会遇到内存问题,这些问题会在应用程序的几种不同的重新启动过程中累积。解决方案只是降低游戏的整体质量和资源量。
我建议尝试更新固件,因为较新的版本可以解决此问题。但是,诺基亚并非很难轻松地升级固件,在大多数情况下,我们必须将设备发送给诺基亚。而且,如果该应用程序不仅仅供我们个人使用,我们必须期望使用N系列设备的任何人都没有最新的固件。
最后,我建议花一些时间在诺基亚论坛上四处逛逛,因为我知道有些帖子涉及内存泄漏和N系列设备。这是一篇似乎可以解决我们遇到的问题的文章。
http://discussion.forum.nokia.com/forum/showthread.php?t=123486