Подтвердить что ты не робот

Может ли утечка памяти в Java

Я получил этот вопрос много раз. Какой хороший способ ответить

4b9b3361

Ответ 1

Может ли быть утечка памяти в Java?

Ответ заключается в том, что это зависит от того, о какой утечке памяти вы говорите.

Утечки памяти Classic C/С++ происходят, когда приложение пренебрегает free или dispose объектом, когда они с ним выполняются, и он течет. Циклические ссылки являются вспомогательным случаем, когда приложение испытывает трудности с пониманием того, когда free/dispose, и пренебрегает этим в результате. Связанные проблемы - это то, где приложение использует объект после его освобождения или пытается освободить его дважды. (Вы могли бы назвать последние проблемы утечкой памяти или просто ошибками. В любом случае...)

Java и другие (полностью 1) управляемые языки в основном не страдают от этих проблем, потому что GC заботится о освобождении объектов, которые больше недоступны. (Конечно, оборванных указателей и двойных проблем не существует, а циклы не являются проблематичными, как и для "умных указателей" C/С++ и других схем подсчета ссылок.)

Но в некоторых случаях GC в Java будет пропускать объекты, которые (с точки зрения программиста) должны быть собраны в мусор. Это происходит, когда GC не может понять, что объект не может быть достигнут:

  • Логика/состояние программы может быть такой, что пути выполнения, которые будут использовать некоторую переменную, не могут быть выполнены. Разработчик может видеть это очевидным, но GC не может быть уверенным и ошибается на стороне осторожности (как это требуется).
  • Программист может ошибаться в этом, и GC избегает того, что в противном случае может привести к оборванной ссылке.

(Обратите внимание, что причины утечек памяти в Java могут быть простыми или довольно тонкими; см. ответ @jonathan.cone для некоторых тонких. Последний потенциально связан с внешними ресурсами, которые вы не должны полагаться на GC для решения в любом случае.)

В любом случае у вас может быть ситуация, когда нежелательные объекты не могут быть собраны в мусор, и повесьте вокруг привязки памяти... утечку памяти.

Тогда возникает проблема, заключающаяся в том, что Java-приложение или библиотека могут выделять объекты с кучей через собственный код, которым необходимо управлять вручную. Если приложение/библиотека ошибочно или используется неправильно, вы можете получить утечку памяти. (Например: утечка памяти Bitmap в Android... отметив, что эта проблема исправлена ​​в более поздних версиях Android.)


1 - Я имею в виду пару вещей. Некоторые управляемые языки позволяют писать неуправляемый код, где вы можете создавать классические утечки памяти. Некоторые другие управляемые языки (или, точнее, языковые реализации) используют подсчет ссылок, а не правильный сбор мусора. Диспетчер хранилищ на основе ссылок требует что-то (например, приложение) для прерывания циклов... или иначе возникнут утечки памяти.

Ответ 2

Ну, учитывая, что java использует сборщик мусора для сбора неиспользуемых объектов, вы не можете иметь свисающий указатель. Однако вы можете сохранить объект в области дольше, чем это необходимо, что можно считать утечкой памяти. Подробнее об этом здесь: http://web.archive.org/web/20120722095536/http://www.ibm.com:80/developerworks/rational/library/05/0816_GuptaPalanki/

Вы проводите тест на это или что-то еще? Потому что это, по крайней мере, A + прямо там.

Ответ 3

Да. Утечки памяти могут возникать даже тогда, когда у вас есть GC. Например, вы можете использовать ресурсы, такие как набор результатов базы данных, которые вы должны закрыть вручную.

Ответ 4

Ответ - да, но это, как правило, результат модели программирования, а не признак какого-либо дефекта в JVM. Это часто случается, когда у фреймворков жизненные циклы отличаются от жизненных циклов JVM. Вот некоторые примеры:

  1. Перезагрузка контекста
  2. Невозможность разыменования наблюдателей (слушателей)
  3. Забыв очистить ресурсы после того, как вы закончили их использовать *

* - Миллиарды консалтинговых долларов были сделаны для разрешения последнего

Ответ 5

Да, в том смысле, что ваше приложение Java может накапливать память с течением времени, что сборщик мусора не может освободиться.

Поддерживая ссылки на ненужные/нежелательные объекты, они никогда не выйдут из области действия, и их память не будет возвращена.

Ответ 6

да, если вы не снимаете ссылки на объекты, они никогда не будут собраны в мусор, а использование памяти увеличится. однако из-за того, как разрабатывается Java, этого трудно достичь, тогда как на некоторых других языках это иногда трудно достичь.

изменить: читать ссылку Amokrane. это хорошо.

Ответ 7

Да, это возможно.

В Effective Java есть пример, включающий стек, реализованный с использованием массивов. Если ваши поп-операции просто уменьшают значение индекса, возможно, есть утечка памяти. Зачем? Поскольку ваш массив все еще имеет ссылку на всплывающее значение, и у вас все еще есть ссылка на объект стека. Поэтому правильная вещь для реализации этого стека должна заключаться в том, чтобы очистить ссылку на всплываемое значение, используя явное присвоение нулей в индексе всплывающего массива.

Ответ 8

В книге " Эффективная Java" приводятся еще две причины "утечек памяти":

  • Однажды вы положили ссылку на объект в Cache и забыли, что он там есть. Ссылка остается в кеше задолго до того, как становится неактуальной. Решение состоит в том, чтобы представить кэш как WeakHashMap
  • в API, где клиенты регистрируют обратные вызовы и не регистрируют их явно. Решение - хранить только слабые ссылки на них.

Ответ 9

Краткий ответ:

Компетентная JVM не имеет утечек памяти, но можно использовать больше памяти, чем необходимо, поскольку еще не все неиспользуемые объекты были собраны сборщиком мусора. Кроме того, сами приложения Java могут содержать ссылки на ненужные им объекты, что может привести к утечке памяти.

Ответ 10

Да, это может быть в контексте, когда программа ошибочно удерживает ссылку на объект, который никогда не будет использоваться снова и, следовательно, не очищается GC.

Примером этого было бы забыть закрыть открытый поток:

class MemoryLeak {

    private void startLeaking() throws IOException {
        StringBuilder input = new StringBuilder();
        URLConnection conn = new URL("www.example.com/file.txt").openConnection();

        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));        

        while (br.readLine() != null) {
            input.append(br.readLine());
        }
    }

    public static void main(String[] args) throws IOException {
        MemoryLeak ml = new MemoryLeak();
        ml.startLeaking();
    }
}

Ответ 11

Один простой ответ: JVM позаботится обо всей вашей инициализации POJO [простых старых java-объектов], пока вы не работаете с JNI. С JNI, если вы сделали какое-либо распределение памяти с помощью собственного кода, вы должны сами позаботиться об этой памяти.

Ответ 12

Да. Утечка памяти - это неиспользуемая память, не отформатированная в диспетчере памяти приложением.

Я видел много раз код Java, который хранит элементы в структуре данных, но элементы никогда не удаляются оттуда, заполняя память до OutOfMemoryError:

void f() {
    List<Integer> w = new ArrayList<Integer>();
    while (true) {
         w.add(new Integer(42));
    }
}

Хотя этот пример слишком очевиден, ошибки памяти Java, как правило, более тонкие. Например, используя Dependency Injection, хранящий огромный объект в компоненте с областью SESSION, не отпуская его, когда объект больше не используется.

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