【问题标题】:OutOfMemoryError AndroidOutOfMemoryError Android
【发布时间】:2012-01-06 09:34:36
【问题描述】:

我的应用程序在大约 5 天前运行良好!今天,我尝试运行它,它绝对疯了!

在它最终抛出内存不足错误之前,我在 logcat 中收到了这条消息

01-06 04:14:17.088: D/dalvikvm(454): GC_FOR_MALLOC freed 5702 objects / 326856 bytes in 76ms  
01-06 04:14:17.228: D/dalvikvm(454): GC_FOR_MALLOC freed 680 objects / 157944 bytes in 57ms
01-06 04:14:17.228: I/dalvikvm-heap(454): Grow heap (frag case) to 2.860MB for 121834-byte allocation
01-06 04:14:17.288: D/dalvikvm(454): GC_FOR_MALLOC freed 1 objects / 81232 bytes in 60ms
01-06 04:14:17.378: D/dalvikvm(454): GC_FOR_MALLOC freed 5 objects / 192 bytes in 65ms
01-06 04:14:17.388: I/dalvikvm-heap(454): Grow heap (frag case) to 2.957MB for 182746-byte allocation
....and so on...

然后最后出现这个错误:

01-06 04:24:49.218: E/AndroidRuntime(511): java.lang.OutOfMemoryError
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:97)
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:136)
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.StringBuilder.append(StringBuilder.java:272)
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.io.BufferedReader.readLine(BufferedReader.java:452)
01-06 04:24:49.218: E/AndroidRuntime(511):  at appsbidder.clientstuff.Utils.openURL(Utils.java:285)
01-06 04:24:49.218: E/AndroidRuntime(511):  at appsbidder.clientstuff.Utils.getFeatured(Utils.java:224)
01-06 04:24:49.218: E/AndroidRuntime(511):  at appsbidder.FeaturedAppsActivity$GridViewAdapter.<init>(FeaturedAppsActivity.java:45)
01-06 04:24:49.218: E/AndroidRuntime(511):  at appsbidder.FeaturedAppsActivity.onCreate(FeaturedAppsActivity.java:28)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.os.Looper.loop(Looper.java:123)
01-06 04:24:49.218: E/AndroidRuntime(511):  at android.app.ActivityThread.main(ActivityThread.java:4627)
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.reflect.Method.invokeNative(Native Method)
01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.reflect.Method.invoke(Method.java:521)
01-06 04:24:49.218: E/AndroidRuntime(511):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
01-06 04:24:49.218: E/AndroidRuntime(511):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
01-06 04:24:49.218: E/AndroidRuntime(511):  at dalvik.system.NativeStart.main(Native Method)

我想我把它缩小到这个代码块,但我不知道为什么它不起作用!它以前一直工作正常。我能想到的唯一问题是现在它必须获取比以前更多的数据,所以某处发生了溢出,但是在哪里呢??

public JSONArray openURL(String urlParams, String url)
  {


    HttpsURLConnection connection = null;
    try {
      System.setProperty("http.keepAlive", "false");
      //Create connection
      connection = (HttpsURLConnection)new URL(url).openConnection();
      connection.setRequestMethod("POST");


      connection.setRequestProperty("Content-Type", 
      "application/x-www-form-urlencoded");

      connection.setRequestProperty("Content-Length", "" + 
          Integer.toString(urlParams.getBytes().length));
      connection.setRequestProperty("Content-Language", "en-US"); 


      connection.setUseCaches(false);
      connection.setDoInput(true);
      connection.setDoOutput(true);

      //Send request
      DataOutputStream wr = new DataOutputStream (
                  connection.getOutputStream ());
      wr.writeBytes (urlParams);
      wr.flush();
      wr.close();

      //Get Response    
      InputStream is = connection.getInputStream();
      BufferedReader rd = new BufferedReader(new InputStreamReader(is));
      String line;
      JSONArray ja = new JSONArray();
      while((line = rd.readLine()) != null) {
          ja = new JSONArray(line);
      }
      rd.close();
      return ja;

    } catch (Exception e) {

      e.printStackTrace();
      return null;

    } finally {

      if(connection != null) {
        connection.disconnect(); 
      }

    }

  }

【问题讨论】:

    标签: android out-of-memory arrays


    【解决方案1】:

    我可以看到你应该看看这个:

          while((line = rd.readLine()) != null) {
              ja = new JSONArray(line);
          }
    

    由于错误是在 readLine 方法调用时引发的。

    01-06 04:24:49.218: E/AndroidRuntime(511):  at java.lang.StringBuilder.append(StringBuilder.java:272)
    01-06 04:24:49.218: E/A ndroidRuntime(511):  at java.io.BufferedReader.readLine(BufferedReader.java:452)
    

    你应该试试这个:

    char[] buffer = new char[8064];
    BufferedReader rd = new BufferedReader(new InputStreamReader(is), buffer.length);
    

    并使用 read 代替 readLine

    rd.read(buffer, 0, buffer.length)
    

    这方面的例子很多。

    编辑:

    来自我的旧项目:

    readResponse(InputStream inputStream) {
    
    ByteArrayOutputStream stream = new ByteArrayOutputStream ();
    byte[] buffer = new byte[8064];
    
    while(true) {
    int rd = inputStream.read(buffer)
    if(rd == -1)break;
    stream.write(buffer, 0 , rd);
    }
    
    stream.flush();
    buffer = stream.toByteArray();
    String response = new String(buffer);
    inputStream.close();
    
    return response;
    }
    

    【讨论】:

    • 这不一定有效,因为 read 方法的第一个参数需要一个 char[] 而不是 byte[] 。
    • 是的,我实际上只是看着它。抱歉,真正的问题是我不能使用这种方式,因为我的“line”变量是一个字符串。只有 readLine 在这里适用,除非我错过了什么
    • 好吧,您正在为“line”分配一个值,该值太大并导致异常。如果“响应”包含换行符 (\n),您可以拆分字符串并以这种方式检索您的行。
    • 你的意思是String类型的值太大了?
    【解决方案2】:

    大概在这里:

    while((line = rd.readLine()) != null) {
    

    如果响应在单行中包含大 json,那么您可以在这一行出现 OutOfMemoryError。您可以通过手动检查收到的响应来验证这一点。

    【讨论】:

    • 如果 JSON 很大,我该如何解决?
    【解决方案3】:

    我认为这行代码是错误的:

    JSONArray ja = new JSONArray();
          while((line = rd.readLine()) != null) {
              ja = new JSONArray(line);   // in every step of loop, you create an object, that is wrong for memory
          }
    

    改为使用:

    JSONArray ja = new JSONArray();
          while((line = rd.readLine()) != null) {
              ja.add(line);
          }
    

    希望这会有所帮助。

    【讨论】:

    • 我试过了,还是一样的问题。你认为它可能是 json 太大了吗?
    • 我不这么认为,但经过小小的搜索,我找到了一个关于这个的帖子,看看这个:stackoverflow.com/questions/2886599/…
    猜你喜欢
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 2011-11-09
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多