... но я считаю, что в какой-то момент во время операции копирования это занимает около 160 МБ кучи
Я нахожу это чрезвычайно удивительным ... поскольку я сомневаюсь, что вы правильно измеряете использование кучи.
Давайте предположим, что ваш код выглядит примерно так:
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("somefile"));
ByteArrayOutputStream baos = new ByteArrayOutputStream(); /* no hint !! */
int b;
while ((b = bis.read()) != -1) {
baos.write((byte) b);
}
byte[] stuff = baos.toByteArray();
Теперь способ, которым ByteArrayOutputStream управляет своим буфером, состоит в том, чтобы выделить начальный размер и (по крайней мере) удвоить буфер при заполнении. Таким образом, в худшем случае baos
может использовать до 80 МБ буфера для хранения файла 40 МБ.
На последнем шаге выделяется новый массив размером ровно baos.size()
байтов для хранения содержимого буфера. Это 40 Мб. Таким образом, максимальный объем используемой памяти должен составлять 120 МБ.
Так, где эти лишние 40 Мб используются? Я предполагаю, что это не так, и что вы на самом деле указываете общий размер кучи, а не объем памяти, занимаемый достижимыми объектами.
Так в чем же решение?
Вы можете использовать буфер с отображением в памяти.
Вы могли бы дать подсказку о размере, когда вы выделяете ByteArrayOutputStream
; например,
ByteArrayOutputStream baos = ByteArrayOutputStream(file.size());
Вы можете полностью отказаться от ByteArrayOutputStream
и читать непосредственно в байтовый массив.
byte[] buffer = new byte[file.size()];
FileInputStream fis = new FileInputStream(file);
int nosRead = fis.read(buffer);
/* check that nosRead == buffer.length and repeat if necessary */
Обе опции 1 и 2 должны иметь пиковое использование памяти 40 МБ при чтении файла 40 МБ; то есть не теряемое пространство.
Было бы полезно, если бы вы опубликовали свой код и описали свою методологию измерения использования памяти.
Я думаю, я мог бы просто расширить ByteArrayOutputStream и переписать этот метод, чтобы вернуть исходный массив напрямую. Есть ли здесь потенциальная опасность, учитывая, что поток и байтовый массив не будут использоваться более одного раза?
Потенциальная опасность состоит в том, что ваши предположения неверны или становится неверным из-за того, что кто-то другой невольно изменил ваш код ...