Android:内存不足错误StringBuilder

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

这是我的方法:

private String sendPostRequest(String url, List<NameValuePair> 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.<init>(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.<init>(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.<init>(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()的错误。 当我尝试与艾米特的答案时,也发生了同样的事情。 有什么toString()。

更新2

从while循环中删除了新的String builder对象的创build,现在我不使用行分隔符。 但是,这并没有太大的区别。 该应用程序首次运行。 但是,如果我试图连续运行2-3次,同样的问题再次发生。

如果你没有足够的内存来存储你的string,你可以:释放一些内存,减less内存消耗,不要将string存储在内存中。

在你的情况下,你需要:

  • 内存来存储响应(大约1.5 + MB)
  • string生成器的内存(大约1.5 + mb)
  • 内存为结果string(大约1.5 + MB连续内存,非常糟糕)
  • 的BufferedReader / InputStreamReader中…等。 (一些公斤)

选项:

  1. 将响应转换为不带string构build器的string 。 这将节省1 + MB。
  2. 以stream的forms读取响应,并将其转换为不带string构build器的string。 请求/响应实体stream 。 这将节省3mb左右
  3. 不要将响应转换为string。 将其作为stream读取并保存到文件或数据库中,或者将stream传递给stream式JSONparsing器。
  4. 在发送您的post请求之前,尽可能多的回忆,并开始祈祷,一切都会好的。

只需将其添加到清单中的<application />标记即可:

 android:largeHeap="true" 

像这样尝试,

 private String sendPostRequest(String url, List<NameValuePair> 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; }