I have a simple code which sends a Http request to my external server to download a .txt file with a size of 100mb. Smaller files, like 40mb are working, but there are some problems with bigger ones. Let me show you some code:
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();
}
}
There's some more code to display progress but it's not important here. The problem is that the file's size is 100mb but Android magically allocates 400mb+ RAM while downloading it and comes with the error:
Waiting for a blocking GC Alloc
WaitForGcToComplete blocked for 12.906ms for cause Alloc
Starting a blocking GC Alloc
Starting a blocking GC Alloc
Suspending all threads took: 35.332ms
Alloc partial concurrent mark sweep GC freed 214(21KB) AllocSpace objects, 1(200MB) LOS objects, 6% free, 216MB/232MB, paused 1.076ms total 130.115ms
Suspending all threads took: 205.400ms
Background sticky concurrent mark sweep GC freed 364(10KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 416MB/416MB, paused 10.448ms total 304.325ms
Starting a blocking GC Alloc Starting a blocking GC Alloc
Alloc partial concurrent mark sweep GC freed 113(3KB) AllocSpace objects, 0(0B) LOS objects, 3% free, 416MB/432MB, paused 290us total 17.611ms
Starting a blocking GC Alloc
Alloc sticky concurrent mark sweep GC freed 31(912B) AllocSpace objects, 0(0B) LOS objects, 3% free, 416MB/432MB, paused 268us total 6.474ms
Starting a blocking GC Alloc
Alloc concurrent mark sweep GC freed 43(13KB) AllocSpace objects, 0(0B) LOS objects, 3% free, 415MB/431MB, paused 268us total 15.008ms
Forcing collection of SoftReferences for 300MB allocation
Starting a blocking GC Alloc
Alloc concurrent mark sweep GC freed 42(1256B) AllocSpace objects, 0(0B) LOS objects, 3% free, 415MB/431MB, paused 286us total 12.426ms
Throwing OutOfMemoryError "Failed to allocate a 314572860 byte allocation with 16770608 free bytes and 96MB until OOM"
When I run the downloading process, I can see on my device that I have 1GB allocated (by system) and 600 mb free while the app uses 20-30 mb. After couple seconds, my app starts to allocate more and more memory and I can see, that it uses 400mb+ and the crash comes when it comes to the maximum as you can see in the logs.
Maybe I don't understand it, but shouldn't it only allocate the required 100mb of RAM to store the chunks of data? I'm nearly 100% sure that there is no leak in my app - memory is being consumed by the downloading process (which is for sure called only once).