2011-02-02 3 views
3

Мы сталкиваемся с утечкой памяти, используя простой, простой и простой код следующим образом. Код предназначен для получения файлов из источника, используйте каждый файл, чтобы что-то сделать, и продолжайте. Этот простой код всегда использует один и тот же файл, но поведение не изменилось.Утечка памяти FileInputStream в цикле считывания файла

package it.datapump.main; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 


public class TifReader { 

public static void main (final String[] a){ 

    for (int i = 0; i < 100000; i++) { 
     try { 
      getBytesFromFile(new File("test.tif")); 
      Thread.sleep(1000); 
      System.gc() ; 
     } catch (Exception ex) { 
     } 
    } 
} 

public static byte[] getBytesFromFile(File file) throws IOException { 
    InputStream is = new FileInputStream(file); 
    long length = file.length(); 

    byte[] bytes = new byte[(int)length]; 
    int offset = 0; 
    int numRead = 0; 
    while (offset < bytes.length 
      && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 
     offset += numRead; 
    } 
    is.close(); 

    // Do something with the read bytes 
    // 

    if (offset < bytes.length) { 
     throw new IOException("Could not completely read file "+file.getName()); 
    } 
    return bytes; 
} 
} 

Теперь ... мы просто не можем видеть действительную причину этого кода, чтобы потреблять память до самого верха, и в конце концов бросает исключение OutOfMemoryError.
Есть идеи?

нечто большее
Проблема возникает с помощью Java Development Kit Version 6 Update 23, но это не на JRE 1.7

+0

Правильно ли это - этот * фрагмент создает ошибку OOM, OOM не связан с частью комментария «Делать что-нибудь с прочитанными байтами»? И никаких исключений не бросали? –

+0

@Andreas_D, не заинтересован в анализе фрагмента. Это абсолютно неправильный способ чтения файла. –

+0

@Vladimir: IMHO, вам нужно уважать вопрос, поставленный OP, а не прокладывать себе путь. И BTW, это не «неправильно», это просто «круглый» способ. –

ответ

0


После потери времени и восстановления на этом мы обнаружили, что проблема связана с тем, как пакет был установлен на целевой машине.
Наш программист построил запущенную банку, содержащую все необходимые банки, вместо того, чтобы использовать те, которые уже установлены на целевой машине. Итак ... «что-то» было другим, даже если мы на самом деле не знаем, что, и теперь процедура не утрачивает память.

Может кто-нибудь объяснить это мне? (Я должен сказать, что я разработчик C/C++, а не Java, и я пишу о работе моего коллеги).

2

Этот код должен работать нормально (за исключением того факта, что создание нового файла так много раз марки не имеет смысла).

Я провел ваш код в цикле 10 миллионов раз, и он не произвел OOME. Фактически, использование памяти было постоянным около 50 Мб.

Итак, я думаю, что проблема должна быть чем-то еще.

+0

Очень хорошо ... Не могли бы вы объяснить, какие IDE вы используете? Какой сценарий? Я имею в виду версию JRE/JDK и так далее? Мы столкнулись с чем-то очень похожим, поскольку проблема возникает только на некоторых машинах, а не на других. –

+0

Последний Java SDK 1.6 на OS X. Идея - это Intellij IDEA 10. –

1

Я бы запустил ваш код против профайлера, например Visual VM, и посмотрел, где находится память.

Я предполагаю, что «что-то с кодом байта» может вызвать проблему. Также вызов System.gc() обычно не рекомендуется, так как сборщик гаражей должен знать себя, когда он должен быть вызван.

+0

Как я уже сказал, в образце cose ничего не делается в пункте «сделать что-то», но проблема все равно возникает. –

+0

хорошо. Я пропустил эти комментарии, когда писал свой ответ. Если вы используете java 1.6, вы можете использовать визуальный vm. В нем есть плагины для netbeans и eclipse. –

0

Поскольку вы эффективно отбрасываете байты, считанные из файла на каждой итерации, я не вижу причин для получения OOME, если размер файла больше, чем стандартный Xmx для вашего процесса JVM (просто процесс мышления с тех пор Я знаю, что файлы TIF известны своим огромным размером по сравнению с другими форматами изображений).

Кроме того, распечатайте номер итерации. Получаете ли вы OOME всегда при одном и том же счете? Или вы используете «байты», считанные из потока файлов?

+0

Число итераций пропорционально количеству памяти, которое вы передаете JVM, поэтому не кажется, что конкретный файл вызывает проблему. –

+0

Я просто забыл сказать, что эти файлы TIF довольно малы. –