Почему этот код для заполнения массива создает утечку памяти? - PullRequest
0 голосов
/ 16 февраля 2011

Я столкнулся с несколько странной проблемой, связанной с простой задачей динамического заполнения массива в Java.Ниже приведен снимок места возникновения проблемы:

entries = new Object[ (n = _entries.length + 1) ] ;

for(i = 0 ; i < n ; i++) {

            entry = ( i == (n - 1) )  ?  addition  :  _entries[i]  ;

            entries[i] = entry ;

            //...

}

Где _entries - источник Array (поле класса);entries инициализируется как Array из Object s

Object[] entries = null ;

, а addition - это Object, который будет добавлен (передается как аргумент метода, в котором находится этот код).


Код проходит компилятор, но при вызове вызывает утечку памяти.Мне удалось сузить причину до строки, где код пытается заполнить новый Array

 entries[i] = entry ;

, однако я не могу придумать ни одной причины, по которой это может вызвать утечку памяти.Я предполагаю, что корень проблемы должен быть либо чрезвычайно глупой ошибкой с моей стороны, либо крайне загадочной проблемой с Java.:-)

Если вам нужно больше информации, дайте мне знать.

Редактировать:

Журнал Tomcat сообщает мне:

Веб-приложение, похоже, запустило поток с именем ..., но не смогло его остановить.Это может привести к утечке памяти.

Кроме того, очевидно, что страница, загружающая класс, не завершает загрузку или загружается очень медленно.

Редактировать:

Проблема может быть где-то еще (в более ожидаемом месте) в конце концов.Очевидно, Tomcat не загружал файлы классов все время, когда я пытался определить неисправный код, и это немного вводило меня в заблуждение.Теперь я подозреваю, что виноват цикл infinte for-each, вызванный дефектной реализацией Iterator в стеке вызовов.В любом случае, спасибо за ваш вклад!Всегда высоко ценю!


Я буду использовать Collection (вероятно, Vector) вместо Array в качестве обходного пути;Тем не менее, я хотел бы знать, в чем здесь проблема.

TIA,

FK82

Ответы [ 4 ]

3 голосов
/ 16 февраля 2011

Итак, о вашем сообщении журнала Tomcat:

Веб-приложение, похоже, запустило поток с именем ..., но не смогло его остановить. Это может привести к утечке памяти.

Это говорит о том, что ваш сервлет или что-то подобное запустило новый поток, и этот поток все еще работает, когда ваш сервлет завершил свою работу. Это совсем не относится к вашему примеру кода (если этот код не тот, что запускает поток).

Лишние потоки, даже больше, когда каждый HTTP-запрос запускает новый (который скоро не завершится), может вызвать утечку памяти, поскольку каждому потоку требуется достаточно места для своего стека, а также может препятствовать сборке мусора путем ссылки объекты, которые больше не нужны. Убедитесь, что ваш поток действительно нужен, и подумайте об использовании вместо этого пула потоков (желательно, если это возможно с помощью контейнера).

1 голос
/ 16 февраля 2011

Это работает для меня,

пожалуйста, найдите образец кода.и измените его на соответственно

class test {

 public static void main(String[] args) {


   String[] str = new String[]{"1","2","3","4","5","6"};

   int n=0;
   Object[] entries = new Object[ (n = 5 + 1) ] ;

    for(int i = 0 ; i < n ; i++) {

            Object entry = ( i == (n - 1) )  ?  new Object()  :  str [i]  ;

            entries[i] = entry ;



    }
   System.out.println(entries[3]);

 }

}
1 голос
/ 16 февраля 2011

Возможно, под утечкой памяти вы имеете в виду исключение OutOfMemoryException?Иногда вы получаете это в Java, если у вас не установлен минимальный размер кучи, достаточно высокий (а также четко определенный максимальный размер кучи) при запуске.Если при запуске создается недостаточно кучи, иногда ее можно использовать быстрее, чем JVM может выделить больше памяти для кучи или для сбора мусора.К сожалению, здесь нет «правильного ответа».Вам просто нужно поиграть с разными настройками, чтобы получить правильный результат (то есть известный как «настройка JVM»).Другими словами, это больше искусство, чем наука.

И если вы не знали, вы передаете аргументы JVM в командной строке при запуске вашей программы -Xmin 250m -Xmax1024 м является примером.Вы должны указать значения в мегабайтах.Первый устанавливает минимальную кучу (при запуске) до 250 мегабайт.Второй аргумент устанавливает максимальный размер кучи равным одному гигабайту.

Еще одна мысль, о которой я думаю, поскольку я тоже озадачен тем, как можно проследить утечку памяти до одной строки кода.

1 голос
/ 16 февраля 2011

Я не вижу утечки памяти, но ваш код сложнее, чем нужно. Как насчет этого:

newLength = $entries.length + 1;
entries = new Object[ newLength ] ;

for(i = 0 ; i < newLength - 1 ; i++) {
        entries[i] = $entries[i];
        //...
}

entries[ newLength - 1 ] = addition;

Нет необходимости проверять, находитесь ли вы в последней записи все время, и вы могли бы использовать метод копирования массива, как предложено Алисон.

Думайте об этом посте как о комментарии. Я просто опубликовал это как ответ, потому что я не знаю, как кодируется в комментариях ...

...