使用LibGDX Net无法在Android上下载100mb文件

时间:2016-09-16 13:14:15

标签: android memory download libgdx garbage-collection

我有一个简单的代码,它向我的外部服务器发送一个Http请求,以下载大小为100mb的.txt文件。较小的文件,如40mb正在工作,但是较大的文件存在一些问题。让我给你看一些代码:

Net.HttpRequest request = new Net.HttpRequest(Net.HttpMethods.GET);
    request.setTimeOut(2500);
    String assetsUrl = "http://111.111.111.111/100mb.txt";
    request.setUrl(assetsUrl);


    // Send the request, listen for the response
    // Asynchronously
    Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
        @Override
        public void handleHttpResponse (Net.HttpResponse httpResponse) {


            InputStream is = httpResponse.getResultAsStream();
            OutputStream os = Gdx.files.local("100mb.txt").write(false);

            byte[] bytes = new byte[1024];
            int count = -1;

            try {

                while ((count = is.read(bytes, 0, bytes.length)) != -1) {
                    os.write(bytes, 0, count);
                }

            } catch (IOException e) {
                e.printStackTrace();
            }


        }

还有一些代码可以显示进度,但这里并不重要。 问题是该文件的大小为100mb,但Android在下载时神奇地分配了400mb + RAM并带有错误:

  

等待阻止GC Alloc

     

WaitForGcToComplete因为Alloc

而被阻止了12.906ms      

启动阻止GC Alloc

     

启动阻止GC Alloc

     

暂停所有线程:35.332ms

     

Alloc部分并发标记扫描GC释放214(21KB)AllocSpace   对象,1(200MB)LOS对象,6%免费,216MB / 232MB,暂停1.076ms   总计130.115ms

     

暂停所有线程:205.400ms

     

后台粘性并发标记扫描GC释放364(10KB)AllocSpace   对象,0(0B)LOS对象,0%免费,416MB / 416MB,暂停10.448ms   总计304.325ms

     

启动阻止GC Alloc启动阻止GC Alloc

     

Alloc部分并发标记扫描GC释放113(3KB)AllocSpace   对象,0(0B)LOS对象,3%免费,416MB / 432MB,总计暂停290us   17.611ms

     

启动阻止GC Alloc

     

Alloc粘性并发标记扫描GC释放31(912B)AllocSpace   对象,0(0B)LOS对象,3%免费,416MB / 432MB,暂停268us   6.474ms

     

启动阻止GC Alloc

     

Alloc并发标记扫描GC释放43(13KB)AllocSpace对象,   0(0B)LOS对象,3%免费,415MB / 431MB,暂停268us总计15.008ms

     

强制收集300位分配的SoftReferences

     

启动阻止GC Alloc

     

Alloc并发标记扫描GC释放了42个(1256B)AllocSpace对象,   0(0B)LOS对象,3%免费,415MB / 431MB,暂停286us总计12.426ms

     

抛出OutOfMemoryError“无法分配314572860字节   分配16770608个空闲字节和96MB直到OOM“

当我运行下载过程时,我可以在我的设备上看到我分配了1GB(按系统分配)和600 MB免费,而应用程序使用20-30 mb。几秒钟之后,我的应用程序开始分配越来越多的内存,我可以看到,它使用了400mb +,当它达到最大值时会出现崩溃,就像你在日志中看到的那样。

也许我不理解它,但它不应该只分配所需的100mb RAM来存储数据块吗? 我几乎100%确定我的应用程序没有泄漏 - 下载过程正在消耗内存(肯定只能调用一次)。

1 个答案:

答案 0 :(得分:1)

你所做的一切都看起来很奇怪,所以我看了一下LibGDX,特别是getResultAsString;最后你得到 com.badlogic.gdx.utils.StreamUtils.copyStreamToString

agent_review.reviewer

这看起来并不可怕,但我的猜测是StringWriter正在发生的事情,导致内部重复重新分配数组。看this answer似乎证实了我的怀疑。

  

StringWriter在内部写入StringBuffer。 StringBuffer基本上是一个char数组的包装器。该阵列具有一定的容量。当容量不足时,StringBuffer将分配一个新的更大的char数组并复制前一个的内容。最后,在StringWriter上调用toString(),它将再次将char数组的内容复制到生成的String的char数组中。

因此,简而言之,您应该找到另一种下载文件的方法。 This question可能会有更强大的解决方案。