Коллекции Java и сборщик мусора - PullRequest
12 голосов
/ 18 января 2010

Небольшой вопрос относительно производительности в веб-приложении на Java.

Предположим, у меня есть List<Rubrique> listRubriques с десятью Rubrique объектами.

A Rubrique содержит один список продуктов (List<product> listProducts) и один список клиентов (List<Client> listClients).

Что именно произойдет в памяти, если я сделаю это:

listRubriques.clear(); listRubriques = null;

Моя точка зрения заключается в том, что, поскольку listRubriques пусто, все мои объекты, на которые ранее ссылался этот список (включая listProducts и listClients), довольно скоро будут собраны сборщиком мусора. Но так как Collection in Java немного сложнее, и так как у меня достаточно проблем с производительностью моего приложения, я задаю вопрос:)

edit: давайте теперь предположим, что мой объект Client содержит List<Client>. Поэтому у меня есть круговая ссылка между моими объектами. Что произойдет, если мой listRubrique установлен на null? На этот раз моя точка зрения будет состоять в том, что мои объекты клиента станут «недоступными», и может создать утечку памяти?

Ответы [ 3 ]

15 голосов
/ 18 января 2010

Фактическая реализация Sun для Java время от времени копирует все ссылочные / живые объекты. Пространство, из которого было скопировано, может быть снова использовано для выделения памяти.

Тем не менее, ваши примеры наносят ущерб производительности. listRubriques.clear() не требуется (за исключением того, что вы держите где-то еще ссылку на него), потому что все, на что ссылается listRubrique, является мусором, в тот момент, когда на listRubriques больше не ссылаются. listRubriques = null может также не понадобиться, если переменная listRubriques впоследствии выйдет из области видимости (возможно, потому что это локальная переменная и метод заканчивается здесь).

Не только вызов clear не нужен, поскольку clear обращается к памяти объекта, который впоследствии больше не используется, к объекту обращаются, и современные процессоры помещают его в свой кэш. Таким образом, мертвый объект явно отправляется в кэш процессора - некоторые, возможно, более полезные данные будут перезаписаны для этой операции.

Эта статья является хорошим справочным материалом для получения дополнительной информации о сборщике мусора Java.

РЕДАКТИРОВАТЬ : Чтобы отреагировать на редактирование вопроса: сборщик мусора (по крайней мере, реализация, используемая Sun) запускается из некоторых корневых ссылок и копирует все объекты, к которым он может обратиться из этих ссылок, и что ссылки на скопированные объекты. Таким образом, ваши объекты с круговой ссылкой являются мусором, так как никакая «внешняя» ссылка не указывает на них, и память будет возвращена в сборщик мусора.

3 голосов
/ 18 января 2010

Если у вас есть:

listRubriques = null;

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

System.gc();

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

Также имеющий

listRubriques.clear();

перед установкой listRubriques в null не требуется.

EDIT : Чтобы ответить на ваш вопрос о циклических ссылках, JVM достаточно умны, чтобы выяснить, что весь граф объектов отключен от любого активно работающего кода, и JVM правильно определит, что все они имеют право на вывоз мусора. Это всегда было верно даже в старые добрые времена подсчета ссылок. Современные JVM просто быстрее и эффективнее. Но они не собирают больше мусора, чем старые виртуальные машины.

1 голос
/ 18 января 2010

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

Единственная ситуация, когда спецификация VM гарантирует, что GC будет работать, - это когда в какой-то момент будет выдано OutOfMemoryError.Перед выбрасыванием OutOfMemoryError виртуальная машина обязана попытаться собрать как минимум столько подходящих экземпляров объекта, чтобы соответствующий запрос выделения памяти мог быть выполнен успешно (но вы все еще не гарантируете, что все допустимые экземплярывзысканных).

...