Создание утечки памяти с Java - PullRequest
2986 голосов
/ 24 июня 2011

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

Каким будет пример?

Ответы [ 54 ]

9 голосов
/ 04 июля 2011

Возможно, интервьюер искал циркулярное справочное решение:

    public static void main(String[] args) {
        while (true) {
            Element first = new Element();
            first.next = new Element();
            first.next.next = first;
        }
    }

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

-Wes Tarle

9 голосов
/ 21 июля 2011

Недавно я исправил пример создания новых объектов GC и Image, но забыл вызвать метод dispose ().

Фрагмент JC Javadoc:

Код приложения должен явно вызывать метод GC.dispose () для освободить ресурсы операционной системы, управляемые каждым экземпляром, когда эти экземпляры больше не требуются. Это особенно важно в Windows95 и Windows98, где операционная система имеет ограниченный количество доступных контекстов устройства.

Фрагмент изображения Javadoc:

Код приложения должен явно вызывать метод Image.dispose () для освободить ресурсы операционной системы, управляемые каждым экземпляром, когда эти экземпляры больше не требуются.

8 голосов
/ 22 июля 2011

Теоретически вы не можете. Модель памяти Java предотвращает это. Однако, поскольку Java должна быть реализована, есть некоторые предостережения, которые вы можете использовать. Зависит от того, что вы можете использовать:

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

  • Если этого нет, есть маленький грязный секрет о java, о котором мало кто знает. Вы можете запросить массив прямого доступа, который не управляется GC, и поэтому может быть легко использован для утечки памяти. Это обеспечивается DirectByteBuffer (http://download.oracle.com/javase/1.5.0/docs/api/java/nio/ByteBuffer.html#allocateDirect(int)).

  • Если вы не можете использовать ни один из них, вы все равно можете сделать утечку памяти, обманув GC. JVM реализована с использованием сборочной сборки мусора. Это означает, что куча разделена на зоны: молодежь, взрослые и старики. Объект, когда он создан, начинается в молодой области. По мере того, как его используют все больше и больше, он перерастает во взрослые, вплоть до старейшин. Скорее всего, объект, который достигает области пожилого возраста, не будет собираться. Вы не можете быть уверены, что какой-либо предмет просочился, и если вы попросите остановить и очистить ГХ, он может очистить его, но в течение длительного периода времени он будет протекать. Больше информации на (http://java.sun.com/docs/hotspot/gc1.4.2/faq.html)

  • Кроме того, объекты класса не обязательно должны быть GC-объектами. Позволь мне сделать это.

8 голосов
/ 07 января 2014

Поток, который не завершается (скажем, бездействует в своем методе выполнения).Это не будет сбор мусора, даже если мы потеряем ссылку на него.Вы можете добавить поля, чтобы сделать объект потока таким большим, как вы хотите.

В текущем топ-ответе перечислены другие приемы, но они кажутся излишними.

8 голосов
/ 21 июня 2018

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

Сначала необходимо отслеживать потребление памяти Java.

Самый простой способ сделать это - использовать утилиту jstat, поставляемую с JVM.

jstat -gcutil <process_id> <timeout>

Он сообщит о потреблении памяти для каждого поколения (Young, Eldery и Old) и времени сбора мусора (Young и Full).

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

Затем вам нужно создать дамп памяти с помощью утилиты jmap:

jmap -dump:live,format=b,file=heap.bin <process_id>

Затем вам нужно проанализировать файл heap.bin с помощью Memory Analyzer, например Eclipse Memory Analyzer (MAT).

MAT проанализирует память и предоставит вам подозрительную информацию об утечках памяти.

7 голосов
/ 03 декабря 2012

Если максимальный размер кучи равен X. Y1 .... Yn нет экземпляров Итак, общая память = количество экземпляров X байтов на экземпляр.M) = Y1 * X1 + ..... + Yn * Xn.Итак, если M> X, то оно превышает пространство кучи.следующие могут быть проблемы в коде 1.Используйте больше экземпляров переменной, чем локальной.2. Создание экземпляров каждый раз вместо объединения объектов.3.Не создавайте объект по запросу.4. Сделав ссылку на объект нулевой после завершения операции. Снова создайте заново, когда это требуется в программе.

7 голосов
/ 06 июня 2014

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

"Как создать утечку памяти с помощью Java?"это открытый вопрос, цель которого - оценить степень опыта разработчика.

Если я спрошу вас: «Есть ли у вас опыт устранения неполадок утечки памяти в Java?», ваш ответ будет простым »Да".Затем мне пришлось бы ответить на вопрос: «Не могли бы вы привести примеры, в которых вы хотели бы устранить утечки памяти?», На которые вы могли бы привести один или два примера.

Однако, когда интервьюер спрашивает «каксоздать утечку памяти с Java? "ожидаемый ответ должен следовать следующим образом:

  • Я столкнулся с утечкой памяти ... (скажем, когда) [это показывает мне опыт]
  • Код, который его вызывалбыл ... (объясните код) [вы исправили это самостоятельно]
  • Исправление, которое я применил, было основано на ... (объясните исправление) [это дает мне возможность спросить подробности об исправлении]
  • Тест, который я провел, был ... [дает мне возможность задать другие методики тестирования]
  • Я задокументировал это таким образом ... [дополнительные баллы.Хорошо, если вы задокументировали это]
  • Итак, разумно подумать, что, если мы последуем этому в обратном порядке, то есть получим исправленный код и удалим исправление, у нас будет утечка памяти.

Когда разработчик не придерживается этой мысли, я пытаюсь дать ему / ей вопрос: «Не могли бы вы дать мне пример того, как Java может утечь память?», А затем «Вы когда-нибудьНужно ли исправлять утечку памяти в Java? "

Обратите внимание, что я не спрашиваю пример того, как утечка памяти в Java.Это было бы глупо.Кому будет интересен разработчик, который может эффективно писать код, который приводит к утечке памяти?

7 голосов
/ 29 августа 2013

Бросить необработанное исключение из метода finalize.

7 голосов
/ 22 июля 2011

Большая часть утечек памяти, которые я видел в процессах Java, выходит из синхронизации.

Процесс A обращается к B через TCP и говорит процессу B что-то создать. B выдает ресурсу идентификатор, скажем, 432423, который A хранит в объекте и использует во время разговора с B. В какой-то момент объект в A восстанавливается сборщиком мусора (возможно, из-за ошибки), но A никогда не сообщает B, что ( возможно еще один баг).

Теперь у A больше нет идентификатора объекта, который он создал в оперативной памяти B, и B не знает, что у A больше нет ссылок на объект. Фактически объект просочился.

7 голосов
/ 22 июля 2011

Несколько предложений:

  • использовать ведение журнала общих имен в контейнере сервлета (возможно, немного провокационно)
  • запустить поток в контейнере сервлета и не возвращаться из негометод запуска
  • загрузка анимированных GIF-файлов в контейнер сервлета (это запустит поток анимации)

Указанные выше эффекты можно «улучшить» путем повторного развертывания приложения;)

Недавно наткнулся на это:

  • Вызов "new java.util.zip.Inflater ();"без вызова "Inflater.end ()" когда-либо

Чтение http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5072161 и связанных проблем для углубленного обсуждения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...