Может ли быть утечка памяти в Java - PullRequest
33 голосов
/ 14 февраля 2011

Мне задают этот вопрос много раз.Какой хороший способ ответить

Ответы [ 12 ]

21 голосов
/ 14 февраля 2011

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

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

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

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

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

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

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

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

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


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

10 голосов
/ 14 февраля 2011

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

Вы берете тест на это или что-то? Потому что это как минимум A + прямо здесь.

8 голосов
/ 14 февраля 2011

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

5 голосов
/ 14 февраля 2011

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

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

* - Миллиарды консалтинговых долларов получены в расчете на последний

4 голосов
/ 14 февраля 2011

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

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

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

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

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

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

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

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

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

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

2 голосов
/ 14 февраля 2011

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

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

Еще более короткий ответ:

Ява является языком и не может иметь утечки памяти, только Java Virtual Машины могут.

1 голос
/ 09 сентября 2018

Да, это может быть в контексте, когда программа ошибочно удерживает ссылку на объект, который никогда больше не будет использоваться, и поэтому он не очищается 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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...