2010-10-04 3 views
4

Я пытаюсь определить, сколько кучи любого данного TYPE_INT_ARGB BufferedImage будет использовать, так что для программы, которая выполняет некоторую обработку изображений, я могу установить разумную максимальную кучу на основе размера изображения, которое мы его кормим.Почему BufferedImage требует столько памяти за пределами размера массива данных?

я написал следующую программу в качестве теста, который я затем используется для определения наименьшей максимальной кучи, под которым он будет работать без OutOfMemoryError:

import java.awt.image.BufferedImage; 

public class Test { 
    public static void main(String[] args) { 
    final int w = Integer.parseInt(args[0]); 
    final int h = Integer.parseInt(args[1]); 

    final BufferedImage img = 
     new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 

    System.out.println((4*w*h) >> 20); 
    } 
} 

(печататься значение является ожидаемый размер int[] в котором хранятся данные пикселя BufferedImage.) Я ожидал найти, что требуемая максимальная куча - это что-то вроде x + c, где x - это размер массива данных, а c - это константа, состоящая из размеров классов, которые загружены, объект BufferedImage и т. д. Это то, что я нашел вместо этого (al л значения в МБ):

 
4*w*h min max heap 
----- ------------ 
    5   - 
10   15 
20   31 
40   61 
80  121 
160  241 

1.5x хорошо подходит для наблюдений. (Обратите внимание, что я не нашел минимума для изображения 5 МБ.) Я не понимаю, что вижу. Каковы эти дополнительные байты?

+0

Может быть вопрос о нобе, но почему 4 * w * h? –

+0

'w * h' - количество пикселей. В изображении 'TYPE_INT_ARGB' каждый пиксель хранится в' int', который должен быть 4 байта.Итак, '4 * w * h' должно быть числом байтов, используемых' int [] 'для хранения своих данных. – uckelman

ответ

1

При дальнейших исследованиях проблема заключается в том, что старое поколение в куче не может достаточно расширить, чтобы разместить массив данных изображения, несмотря на то, что в куче в достаточной степени имеется свободная память.

Дополнительную информацию о том, как развернуть Старое Поколение, см. this question.

4

Кажется, что ошибка в виртуальной машине Oracle появилась где-то между 1.6.0_16 и 1.6.0_20. Вы даже можете уменьшить проблему до выделения массива int, поскольку проблема связана не только с BufferedImage.

С 1.6.0_16 мне нужна куча не менее 413 МБ, чтобы выделить массив int с 100 000 000 элементов, что кажется разумным. С 1.6.0_20 для этой же операции требуется куча памяти не менее 573 МБ, хотя при распределении массива фактически используются только 400 000 000 байт.

+0

Разница довольно большая, но не огромная. Возможно, они добавили некоторые дополнительные внутренние бухгалтерские книги в массивы или что-то в этом роде. Не должно быть слишком сложно узнать, источник по-прежнему свободен? –

0

Используйте BigBufferedImage вместо BufferedImage. Он сохраняет изображение на жестком диске и вам не нужно беспокоиться о размере кучи или пределе физической памяти. Он может хранить максимум 2,147,483,647 пикселей (или 46,340 x 46,340 пикселей).

Создать аз опустошить BigBufferedImage:

BigBufferedImage image = BigBufferedImage.create(
      tempDir, width, height, type); 

Загрузите существующее изображение в BigBufferedImage:

BigBufferedImage image = BigBufferedImage.create(
      imagePath, tempDir, type); 

Отрендерьте часть изображения:

part = image.getSubimage(x, y, width, height); 

Дополнительную информацию об обработке большого изображения read this article.

Смежные вопросы