Android:Out of Memory错误StringBuilder

在我的应用程序中,我以JSON的forms从服务器获取数据。 数据大约为1.5 MB。 该应用程序可以工作,但有时它会在从服务器获取OutOfMemoryError的数据时崩溃。

这是我的方法:

private String sendPostRequest(String url, List params) throws Exception { String ret = null; BufferedReader bufferedReader = null; HttpClient httpClient = new DefaultHttpClient(); HttpPost request = new HttpPost(url); try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params); request.setEntity(entity); HttpResponse response = httpClient.execute(request); bufferedReader = new BufferedReader(new InputStreamReader(response .getEntity().getContent())); StringBuilder stringBuilder = new StringBuilder(""); StringBuilder stringBuilder2; String line = ""; //String LineSeparator = System.getProperty("line.separator"); while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line); } bufferedReader.close(); ret = stringBuilder.toString(); stringBuilder = null; } catch (ClientProtocolException e) { e.printStackTrace(); // TODO: report an error } catch (IOException e) { e.printStackTrace(); // TODO: report an error } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); // TODO Auto-generated catch block } } } return ret; } 

我尝试在使用后将StringBuilder设置为null但没有帮助。 我发布下面的logcat跟踪:

 10-23 03:39:25.271: E/dalvikvm-heap(1011): Out of memory on a 4116282-byte allocation. 10-23 03:39:25.271: I/dalvikvm(1011): "AsyncTask #1" prio=5 tid=11 RUNNABLE 10-23 03:39:25.271: I/dalvikvm(1011): | group="main" sCount=0 dsCount=0 obj=0x417c5e88 self=0x2a1d1db8 10-23 03:39:25.271: I/dalvikvm(1011): | sysTid=1025 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=706552328 10-23 03:39:25.271: I/dalvikvm(1011): | state=R schedstat=( 3053328788 23773807212 6541 ) utm=241 stm=64 core=0 10-23 03:39:25.271: I/dalvikvm(1011): at java.lang.String.(String.java:~422) 10-23 03:39:25.271: I/dalvikvm(1011): at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:642) 10-23 03:39:25.282: I/dalvikvm(1011): at java.lang.StringBuilder.toString(StringBuilder.java:663) 10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.sendPostRequest(ServerConnect.java:128) 10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.Sync(ServerConnect.java:61) 10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.datalayer.DBSync.Login(DBSync.java:59) 10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:52) 10-23 03:39:25.282: I/dalvikvm(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:1) 10-23 03:39:25.282: I/dalvikvm(1011): at android.os.AsyncTask$2.call(AsyncTask.java:287) 10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:234) 10-23 03:39:25.282: I/dalvikvm(1011): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 10-23 03:39:25.282: I/dalvikvm(1011): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 10-23 03:39:25.282: I/dalvikvm(1011): at java.lang.Thread.run(Thread.java:841) 10-23 03:39:25.282: W/dalvikvm(1011): threadid=11: thread exiting with uncaught exception (group=0x41465700) 10-23 03:39:25.292: I/Choreographer(1011): Skipped 30 frames! The application may be doing too much work on its main thread. 10-23 03:39:25.491: E/AndroidRuntime(1011): FATAL EXCEPTION: AsyncTask #1 10-23 03:39:25.491: E/AndroidRuntime(1011): java.lang.RuntimeException: An error occured while executing doInBackground() 10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$3.done(AsyncTask.java:299) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.setException(FutureTask.java:219) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:239) 10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.Thread.run(Thread.java:841) 10-23 03:39:25.491: E/AndroidRuntime(1011): Caused by: java.lang.OutOfMemoryError 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.String.(String.java:422) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:642) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.lang.StringBuilder.toString(StringBuilder.java:663) 10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.sendPostRequest(ServerConnect.java:128) 10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.ServerConnect.Sync(ServerConnect.java:61) 10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.datalayer.DBSync.Login(DBSync.java:59) 10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:52) 10-23 03:39:25.491: E/AndroidRuntime(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.doInBackground(SyncDBTask.java:1) 10-23 03:39:25.491: E/AndroidRuntime(1011): at android.os.AsyncTask$2.call(AsyncTask.java:287) 10-23 03:39:25.491: E/AndroidRuntime(1011): at java.util.concurrent.FutureTask.run(FutureTask.java:234) 10-23 03:39:25.491: E/AndroidRuntime(1011): ... 4 more 10-23 03:39:28.091: E/WindowManager(1011): Activity com.dzo.dispatchcrude.driverapp.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4178fcb0 VE.... R.....ID 0,0-479,96} that was originally added here 10-23 03:39:28.091: E/WindowManager(1011): android.view.WindowLeaked: Activity com.dzo.dispatchcrude.driverapp.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4178fcb0 VE.... R.....ID 0,0-479,96} that was originally added here 10-23 03:39:28.091: E/WindowManager(1011): at android.view.ViewRootImpl.(ViewRootImpl.java:345) 10-23 03:39:28.091: E/WindowManager(1011): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:239) 10-23 03:39:28.091: E/WindowManager(1011): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 10-23 03:39:28.091: E/WindowManager(1011): at android.app.Dialog.show(Dialog.java:281) 10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.SyncDBTask.onPreExecute(SyncDBTask.java:43) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.execute(AsyncTask.java:534) 10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.LoginAsyncTask.onPostExecute(LoginAsyncTask.java:87) 10-23 03:39:28.091: E/WindowManager(1011): at com.dzo.dispatchcrude.driverapp.asynctask.LoginAsyncTask.onPostExecute(LoginAsyncTask.java:1) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.finish(AsyncTask.java:631) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask.access$600(AsyncTask.java:177) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.Handler.dispatchMessage(Handler.java:99) 10-23 03:39:28.091: E/WindowManager(1011): at android.os.Looper.loop(Looper.java:137) 10-23 03:39:28.091: E/WindowManager(1011): at android.app.ActivityThread.main(ActivityThread.java:5103) 10-23 03:39:28.091: E/WindowManager(1011): at java.lang.reflect.Method.invokeNative(Native Method) 10-23 03:39:28.091: E/WindowManager(1011): at java.lang.reflect.Method.invoke(Method.java:525) 10-23 03:39:28.091: E/WindowManager(1011): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 10-23 03:39:28.091: E/WindowManager(1011): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 10-23 03:39:28.091: E/WindowManager(1011): at dalvik.system.NativeStart.main(Native Method) 10-23 03:44:25.761: I/Process(1011): Sending signal. PID: 1011 SIG: 9 

更新1

我尝试了这种方法 ,它在我的情况下也给了toString()错误,它给了toString()错误。 当我尝试Amit的回答时,同样的事情发生了。 toString()有什么用。

更新2

从while循环中删除了新的String构建器对象的创建,现在我没有使用行分隔符。 但是,它没有太大的区别。 该应用程序首次运行。 但是,如果我尝试连续运行2-3次,则会再次出现同样的问题。

如果没有足够的内存来存储字符串,您可以:释放一些内存,减少内存消耗,不要将字符串存储在内存中。

在您的情况下,您需要:

  • 用于存储响应的内存(大约1.5 + mb)
  • 字符串生成器的内存(大约1.5 + mb)
  • 结果字符串的内存(大约1.5 + mb连续内存,非常糟糕)
  • 的BufferedReader / InputStreamReader中…等。 (几公斤)

选项:

  1. 将响应转换为不带字符串构建器的String。 它将节省1 + mb。
  2. 将响应作为流读取并将其转换为不带字符串构建器的String。 请求/响应实体流 。 它将节省约3mb
  3. 不要将响应转换为字符串。 将其作为流读取并保存到文件或数据库,或者为流式JSON解析器提供流。
  4. 在发送您的post请求之前,尽可能多地释放内存并开始祈祷一切都会好起来的。

只需将其添加到清单中的标记:

 android:largeHeap="true" 

试试这样,

 private String sendPostRequest(String url, List params) throws Exception { String ret = null; BufferedReader bufferedReader = null; HttpClient httpClient = new DefaultHttpClient(); HttpPost request = new HttpPost(url); try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params); request.setEntity(entity); HttpResponse response = httpClient.execute(request); bufferedReader = new BufferedReader(new InputStreamReader(response .getEntity().getContent())); String line = ""; while ((line = bufferedReader.readLine()) != null) { ret =ret +line; } bufferedReader.close(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return ret; }