Avoid out of memory errors when using buffers.

pull/27/head
Fox2Code 3 years ago
parent bc5bb2ab80
commit 6ecf659208

@ -1,5 +1,9 @@
package com.fox2code.mmm.utils; package com.fox2code.mmm.utils;
import android.os.Build;
import androidx.annotation.NonNull;
import com.topjohnwu.superuser.io.SuFile; import com.topjohnwu.superuser.io.SuFile;
import com.topjohnwu.superuser.io.SuFileInputStream; import com.topjohnwu.superuser.io.SuFileInputStream;
import com.topjohnwu.superuser.io.SuFileOutputStream; import com.topjohnwu.superuser.io.SuFileOutputStream;
@ -18,6 +22,8 @@ import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
public class Files { public class Files {
private static final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
public static void write(File file, byte[] bytes) throws IOException { public static void write(File file, byte[] bytes) throws IOException {
try (OutputStream outputStream = new FileOutputStream(file)) { try (OutputStream outputStream = new FileOutputStream(file)) {
outputStream.write(bytes); outputStream.write(bytes);
@ -63,8 +69,24 @@ public class Files {
} catch (IOException ignored) {} } catch (IOException ignored) {}
} }
public static ByteArrayOutputStream makeBuffer(long capacity) {
// Cap buffer to 1 Gib (or 512 Mib for 32bit) to avoid memory errors
return Files.makeBuffer((int) Math.min(capacity, is64bit ? 0x40000000 : 0x20000000));
}
public static ByteArrayOutputStream makeBuffer(int capacity) {
return new ByteArrayOutputStream(Math.max(0x20, capacity)) {
@NonNull
@Override
public byte[] toByteArray() {
return this.buf.length == this.count ?
this.buf : super.toByteArray();
}
};
}
public static byte[] readAllBytes(InputStream inputStream) throws IOException { public static byte[] readAllBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ByteArrayOutputStream buffer = Files.makeBuffer(inputStream.available());
copy(inputStream, buffer); copy(inputStream, buffer);
return buffer.toByteArray(); return buffer.toByteArray();
} }

@ -225,8 +225,7 @@ public class Http {
byte[] buff = new byte[1024 * 4]; byte[] buff = new byte[1024 * 4];
long downloaded = 0; long downloaded = 0;
long target = responseBody.contentLength(); long target = responseBody.contentLength();
ByteArrayOutputStream byteArrayOutputStream = ByteArrayOutputStream byteArrayOutputStream = Files.makeBuffer(target);
new ByteArrayOutputStream();
int divider = 1; // Make everything go in an int int divider = 1; // Make everything go in an int
while ((target / divider) > (Integer.MAX_VALUE / 2)) { while ((target / divider) > (Integer.MAX_VALUE / 2)) {
divider *= 2; divider *= 2;

Loading…
Cancel
Save