OutOfMemoryError: Failed to allocate a 8208 byte allocation with 3418760 free byte
liangjingkanji opened this issue · 8 comments
✍️ Describe the bug
Downloading large files (over 150mb) crashes, I'm sure it's Chucker's problem
Exception
Throwing OutOfMemoryError "Failed to allocate a 32 byte allocation with 4673640 free bytes and 4564KB until OOM, target footprint 268435456, growth limit 268435456; failed due to fragmentation (largest possible contiguous allocation 0 bytes). Number of 256KB sized free regions are: 0" (VmSize 6440568 kB, recursive case)
Use
if (BuildConfig.DEBUG) {
addInterceptor(
ChuckerInterceptor.Builder(this@App)
.collector(ChuckerCollector(this@App))
.maxContentLength(250000L)
.redactHeaders(emptySet())
.alwaysReadResponseBody(false)
.build()
)
}
💣 Steps to reproduce
- Clone https://github.com/liangjingkanji/Net/tree/debug
- installing - Runing
- Wait for the download to be about 150mb
- Crash
🔧 Expected behavior
Do not crash when downloading large files
📷 Screenshots
📱 Tech info
- Device: Android Simulator
- OS: Android 13
- Chucker version: 3.5.2
📄 Additional context
I've recommended your project to others a long time ago
Downloading large files (over 150mb) crashes, I'm sure it's Chucker's problem
Can we get a reproducer of some sorts?
What do you mean? You can reproduce the problem by running the demo
I have deleted irrelevant content
Thanks for the repro @liangjingkanji
Yes I was able to reproduce with it. I'll look into it and try whenever I'll find time
I think this method returns wrong result
com.chuckerteam.chucker.internal.support.IOUtils#isPlaintext
ChuckerInterceptor will try to parse the binary, For example application/octet-stream
I think this method returns wrong result
com.chuckerteam.chucker.internal.support.IOUtils#isPlaintext
Yup that could be the reason.
Still you could have a 100Mb JSON response and Chucker will fail with a similar reason
It also fails if I upload the InputStream, Because the ChuckerInterceptor attempt will cause call RequestBody.writeTo
fun InputStream.toRequestBody(
contentType: MediaType? = MediaConst.OCTET_STREAM,
contentLength: Long? = null
): RequestBody {
return object : RequestBody() {
override fun contentType() = contentType
val availableLength: Long by lazy {
if (contentLength != null) return@lazy contentLength
val availableLength = available()
if (availableLength == 0) -1L else availableLength.toLong()
}
override fun contentLength(): Long {
return availableLength
}
override fun writeTo(sink: BufferedSink) {
source().use { source ->
sink.writeAll(source)
}
}
}
}
@liangjingkanji is this somethign you'll be up for attempting to fix?
Ok, I'll attempting to fix this