AndroidでInputStreamをStringに変換しようとするとOOMが発生する
InputStreamをStringに変換しようとするとOutOfMemoryErrorが発生します。
変換しようとしているInputStreamはAndroidのプロジェクトのrawフォルダの中にあるバイナリファイル(5.5MB)を次のようにInputStreamに変換したものです。
OoMがスローされないよう改善できませんか?
InputStream is = this.getRawResouces().openRawResouce();
メモリが876MBの環境でテストしています。
ソースコード
readメソッドを使って書いたコード
static String convertInputStreamToString(InputStream is) throws IOException {
InputStreamReader reader = new InputStreamReader(is);
StringBuilder builder = new StringBuilder();
char[] buf = new char[512];
int numRead;
while (0 <= (numRead = reader.read(buf))) {
builder.append(buf, 0, numRead);
}
buf=null;
return builder.toString();//ココでOoM発生
}
readLine
static String inputStreamToString(InputStream is){
BufferedReader reader = null;
try{
reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
}
catch (UnsupportedEncodingException e){
e.printStackTrace();
}
StringBuilder sb = new StringBuilder();
String b = null;
try{
while ((b=reader.readLine()) !=null){
sb.append(b);
}
}
catch (IOException e){
}
return sb.toString();
}
呼び出し元のコード
private void checkVersion() throws Throwable{
//呼び出し元は、onResume()のonClick()
InputStream versionStream=this.getResources().openRawResource(R.raw.git);
String verchecked=Event.convertInputStreamToString(versionStream);
//ココでreadメソッドを使って書いたコードを使って変換しようとするが、OoM発生、スローされる
versionStream.close();//closeは書いている
java.lang.Process p = null;
TextView vertext=(TextView) findViewById(R.id.version);
try{
p=Runtime.getRuntime().exec(verchecked+" version");
verchecked=null;//vercheckedはもう使わないからnull
InputStream returnVerison=p.getInputStream();//結果を返す
p=null;//pはもう使わないからnullを代入
String ver=Event.convertInputStreamToString(returnVerison);
returnVerison.close();
vertext.setText(ver);
ver=null;
}catch (IOException e){
e.printStackTrace();
vertext.setText("取得失敗: "+e);
}
vertext=null;
}
protected void onResume(){
super.onResume();
//このクラスはMainActivity(最初に呼び出されるActivity)から呼び出される
Button Update=(Button) findViewById(R.id.UpdateButton);
Update.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View p1){
try{
checkVersion();
}catch(OutOfMemoryError e){
e.printStackTrace();
Toast.makeText(GitUpdate.this,"取得失敗:"+e,Toast.LENGTH_SHORT).show();
}
}
});
ヒープ
Android StudioでMemoryの様子を見てみました。一応画像貼っておきます。
へこんでいるところがInputStreamを変換したところです。
MB単位です。
totalMemory(),MaxMemory()
7 ,96
スタックトレース
06-22 20:06:54.681 W/System.err(28046): java.lang.OutOfMemoryError
06-22 20:06:54.681 W/System.err(28046): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
06-22 20:06:54.681 W/System.err(28046): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
06-22 20:06:54.681 W/System.err(28046): at java.lang.StringBuilder.append(StringBuilder.java:216)
06-22 20:06:54.681 W/System.err(28046): at java.lang.ProcessManager.exec(ProcessManager.java:211)
06-22 20:06:54.681 W/System.err(28046): at java.lang.Runtime.exec(Runtime.java:173)
06-22 20:06:54.681 W/System.err(28046): at java.lang.Runtime.exec(Runtime.java:246)
06-22 20:06:54.681 W/System.err(28046): at java.lang.Runtime.exec(Runtime.java:189)
06-22 20:06:54.681 W/System.err(28046): at com.jimdo.solarand.git.GitUpdate.checkVersion(GitUpdate.java:153)
06-22 20:06:54.681 W/System.err(28046): at com.jimdo.solarand.git.GitUpdate.access$1000009(GitUpdate.java)
06-22 20:06:54.681 W/System.err(28046): at com.jimdo.solarand.git.GitUpdate$100000001.onClick(GitUpdate.java:50)
06-22 20:06:54.681 W/System.err(28046): at android.view.View.performClick(View.java:4487)
06-22 20:06:54.681 W/System.err(28046): at android.view.View$PerformClick.run(View.java:18746)
06-22 20:06:54.691 W/System.err(28046): at android.os.Handler.handleCallback(Handler.java:733)
06-22 20:06:54.691 W/System.err(28046): at android.os.Handler.dispatchMessage(Handler.java:95)
06-22 20:06:54.691 W/System.err(28046): at android.os.Looper.loop(Looper.java:149)
06-22 20:06:54.691 W/System.err(28046): at android.app.ActivityThread.main(ActivityThread.java:5257)
06-22 20:06:54.691 W/System.err(28046): at java.lang.reflect.Method.invokeNative(Native Method)
06-22 20:06:54.691 W/System.err(28046): at java.lang.reflect.Method.invoke(Method.java:515)
06-22 20:06:54.691 W/System.err(28046): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
06-22 20:06:54.691 W/System.err(28046): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
06-22 20:06:54.691 W/System.err(28046): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
06-22 20:06:54.691 W/System.err(28046): at de.robv.android.xposed.XposedBridge.main(Native Method)
06-22 20:06:54.691 W/System.err(28046): at dalvik.system.NativeStart.main(Native Method)
その他情報
解決を早めるために、別サイトにも投稿させて頂きました。