2012-04-16 3 views
4

Мое приложение в основном photo browser. Мой подход (не судите меня, я новичок в java) должен был иметь ArrayList, заполненный BufferedImages, а затем добавить изображения в JList (слева).java heap memory issue

Это, как я получаю изображение:

private void getFullImage() { 

     BufferedImage im = null;   


     ImageReader imageReader = null; 
      try { 
       System.out.println("Loading "+original+"..."); 
       String suffix = Utils.getFileExt(original.getName(), "jpg"); 
       @SuppressWarnings("rawtypes") 
       Iterator readers = ImageIO.getImageReadersBySuffix(suffix); 
       imageReader = (ImageReader)readers.next(); 
       imageReader.setInput(new FileImageInputStream(original)); 
       im = imageReader.read(0); 
       imageReader.dispose(); 
      } catch (Exception e) 
      { 
       e.printStackTrace(); 
      } 

     this.img = im; 
    } 

, а затем, после того, как я принес все данные, я хотел бы добавить изображения к моему JList:

Vector vector = new Vector(); 
    JPanel container = null; 
    PhotoPanel pp = null; 
    Photo p = null; 
    for(int i=0;i<files.length;i++) 
    { 
     p = new Photo(files[i]); 
     pp = new PhotoPanel(p); 
     container = new JPanel(new BorderLayout()); 
     container.add(pp,BorderLayout.CENTER); 
             container.setBorder(BorderFactory.createTitledBorder(p.getTitle())); 
           vector.addElement(container); 
    } 
    plist.setListData(vector); 

Если у меня есть, например, 10 файлов, приложение работает очень хорошо. Проблема заключается в том, что у меня появляется гораздо больше изображений. Тогда я получаю исключение: Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space. Итак, я знаю, что мой подход очень плохой, и мне интересно, как мне взять и сохранить все изображения и показать их в JList. Может быть, использовать кэш-память? Я кое-что прочитал о SoftReference, но я действительно не знаю, как его использовать. Благодарю.

+0

@ Андрю, который будет толкать границу, но все равно не будет работать для произвольного количества фотографий. –

+0

@Jakub думаю [@ TheLima] (http://stackoverflow.com/a/10174948/418556) гвоздь. Шум удален. –

ответ

5

Есть два основных возможных причин проблемы:


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

Я не уверен, что это происходит только с NetBeans или всеми инструментами разработки. Но в любом случае для этого требуется действительно абсурдный объем печати, и я сомневаюсь, что вы загрузили столько файлов.

В любом случае, если ваше намерение с линией System.out.println("Loading "+original+"..."); является постоянным/производственным протоколом, а не тем, что вы наделите кодом только временно для целей разработки/отладки, тогда вам будет лучше с надлежащим Logger. Вы можете прочитать версию инструкций TL, DR в this SO answer, и вы можете читать дальше, включая официальную документацию, через ссылки, предоставленные там.


Другая причина, которая, безусловно, ваша, заключается в том, что вы загружаете слишком много данных одновременно. Решения должны либо:

  1. Уменьшить изображение (сделать миниатюры) и показать только полноразмерную версию выбранного изображения. Обратите внимание, что это быстрый метод решения, и он не рекомендуется! ! Так как это может быть слишком много для системы, чтобы выдержать.
  2. Только изображения отображаются на видимой части загруженного интерфейса (или миниатюры указанных изображений, для комбинированного, лучшего решения) и загружают новые изображения (и выгружают другие), когда интерфейс перемещается.
+0

Вы можете «продвинуть границы дальше» с помощью первого метода, увеличив пространство кучи, назначенное приложению, но второй подход намного лучше. +1 –

+0

Хорошо, и как я возьму второй подход? – Teo

+0

Когда пользователь прокручивает доступные изображения, отбросьте одно изображение и добавьте другое. Или загрузите x-изображения и отобразите x-2, когда пользователь прокручивается, загружает еще один, когда вы показываете одно из уже загруженных, но не отображаемых изображений. –

0

Я много боролся с большими изображениями (в SWT), и эти OutOfMemory и NoMoreHandles (что может случиться, даже если памяти недостаточно) были кошмаром. Я думаю, что нет никакого способа сохранить большие изображения или иметь много изображений в памяти. Я согласен с комментарием Андрея, но просто хотел добавить, что в зависимости от ваших требований вы можете попытаться расширить холст (или что бы там ни было в Swing) и DRAW ваши изображения непосредственно на нем, не удерживая их в памяти (аналогично для PaperClips # PrintPreview).Конечно, вам нужно будет иметь некоторые вычисления для правильного отображения изображений, но я думаю, что в этом случае вы могли бы преодолеть свои проблемы с памятью (но получить некоторые другие проблемы :))