Java Midlet を搭載した Nokia 携帯電話でオーディオのスニペットを繰り返しキャプチャしたいと考えています。私の現在の経験では、Sun のドキュメント ( http://java.sun.com/javame/reference/apis/jsr135/javax/microedition/media/control/RecordControl.htmlを参照) のコードを使用し、これを " while(true)" ループは機能しますが、アプリケーションは電話のすべてのメモリをゆっくりと消費し、プログラムは最終的に例外をスローして、それ以上の録音を開始できません。
消費されるメモリは Java ヒープ メモリではありません---私のサンプル プログラム (下記) は、Java メモリが約 185,000 バイトでほぼ静的であることを示しています--- しかし、Nokia が提供する基盤となるサポート ライブラリに何らかのメモリ リークがあります。Java アプリケーションをしばらく実行した後に別の (Java 以外の) アプリケーション (Web ブラウザなど) を起動しようとすると、メモリ不足の警告が表示されて電話がそのアプリケーションを強制終了するため、メモリ リークが発生すると考えられます。
ドキュメントの Sun の標準的な例で採用されているものとは異なるいくつかのアプローチを試しました (ループのたびにすべてを初期化し、できるだけ多くの初期化を 1 回だけ行い、厳密には必要ではないはずの割り当て解除スタイルの関数をできるだけ多く呼び出します)。等。)。どれも成功していないようです。以下は、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) {}
}