Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java StringBuilder setLength处奇怪的OutOfMemoryError(0)_Java_Android_Out Of Memory_Stringbuilder - Fatal编程技术网

Java StringBuilder setLength处奇怪的OutOfMemoryError(0)

Java StringBuilder setLength处奇怪的OutOfMemoryError(0),java,android,out-of-memory,stringbuilder,Java,Android,Out Of Memory,Stringbuilder,似乎没有人报告过类似的情况。。。我完全不知道发生了什么 我有一个8Mb大小的StringBuilder来处理一个大的字符串结果。我正在尝试重用StringBuilder。我认为设置length=0只会重置计数器,而不会分配新内存 try { //result.length() around 4Mb StringBuilder sBuilder = new StringBuilder(result.length()); result = DoSometh

似乎没有人报告过类似的情况。。。我完全不知道发生了什么

我有一个8Mb大小的
StringBuilder
来处理一个大的
字符串结果。我正在尝试重用
StringBuilder
。我认为设置length=0只会重置计数器,而不会分配新内存

try {
      //result.length() around 4Mb
        StringBuilder sBuilder = new StringBuilder(result.length());
        result = DoSomethingToResult1(sBuilder, result); //shrink result a bit using replaceAll

        try {

            sssBuilder.setLength(0);
            result = DoSomethingToResult2(sBuilder, result); //shrink result further using replaceAll
        } catch (OutOfMemoryError e) {
             Log.d(TAG, "Out of Memory on 2");
        }

        try {
            sBuilder.setLength(0);  //OutOfMemory thrown here.          
            result = DoSomethingToResult3(sBuilder, result); //shrink result even further using replaceAll
        } catch (OutOfMemoryError e) {
             Log.d(TAG, "Out of Memory on 3");
        }

    } catch (OutOfMemoryError e) {
                Log.d(TAG, "Cannot create sBuilder");
    }
该进程通常在第二个
setLength(0)
时终止,有时在第一个
setLength(0)
时终止,但它始终可以在开始时创建
sBuilder

DoSomethingToResult
中,我将
result
分割成100Kb大小的块,并逐个附加到
sBuilder
中,返回sBuilder.toString()。所以问题不是来自
replaceAll
。由于它通过了第一个进程,我认为
toString()
也不是问题所在

我试过:

sBuilder.setLength(0);
System.gc();
try{
    Thread.sleep(1000);
}catch(Exception e){};

两者都失败了

日志输出:

E/dalvikvm-heap(27130): Out of memory on a 8723792-byte allocation.
I/dalvikvm(27130): "AsyncTask #1" prio=5 tid=11 RUNNABLE
I/dalvikvm(27130):   | group="main" sCount=0 dsCount=0 obj=0x42036a18 self=0x51c2eb08
I/dalvikvm(27130):   | sysTid=27151 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1371731208
I/dalvikvm(27130):   | schedstat=( 0 0 0 ) utm=197 stm=17 core=1
I/dalvikvm(27130):   at java.lang.AbstractStringBuilder.setLength(AbstractStringBuilder.java:~567)
I/dalvikvm(27130):   at java.lang.StringBuilder.setLength(StringBuilder.java:44)

将长度设置为0不会自动调用GC来启动。您可以做的是创建一个循环并调用System.gc,然后等待一段时间,直到可用内存增加。然后打破循环,继续下一个过程


您还可以尝试分配一个新的构建器,而不是在每次迭代中清除缓冲区。

您是否并行运行任何异步任务?您可以尝试使用jdk附带的工具jvisualvm来分析执行情况?也许有什么你没有考虑到的,因为对我来说,只有几MB的OutOfMemory是很奇怪的。另外,关于这个问题有一个小讨论。@MalaKa这个问题看起来和你提供的问题链接一样。是的,这就是为什么我在评论中提供了一个指向其中一个答案的链接,其中的讨论可能会很有趣(并支持您的答案)。有什么问题吗?@MalaKa在想这是否应该标记为重复。好的,我明白了。但我不这么认为,因为这是一个关于特定问题的问题,而另一个问题是更多的最佳实践。相似,但对我来说不是重复的。
E/dalvikvm-heap(27130): Out of memory on a 8723792-byte allocation.
I/dalvikvm(27130): "AsyncTask #1" prio=5 tid=11 RUNNABLE
I/dalvikvm(27130):   | group="main" sCount=0 dsCount=0 obj=0x42036a18 self=0x51c2eb08
I/dalvikvm(27130):   | sysTid=27151 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1371731208
I/dalvikvm(27130):   | schedstat=( 0 0 0 ) utm=197 stm=17 core=1
I/dalvikvm(27130):   at java.lang.AbstractStringBuilder.setLength(AbstractStringBuilder.java:~567)
I/dalvikvm(27130):   at java.lang.StringBuilder.setLength(StringBuilder.java:44)