Перемещает ли виртуальная машина Java объекты в памяти, и если да, то как?

StackOverflow https://stackoverflow.com/questions/88852

Вопрос

Перемещает ли когда-либо виртуальная машина Java объекты в памяти, и если да, то как она обновляет ссылки на перемещенный объект?

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

Мои две идеи на данный момент таковы:

  1. Сохраняйте косвенную ссылку где-нибудь, которая не перемещается в течение всего времени существования объекта, и которую мы обновляем, если объект перемещается.Но как управлять этими косвенными действиями?
  2. Сохраняйте список обратных ссылок для каждого объекта, чтобы мы знали, что нужно обновить, если объект будет перемещен.Конечно, это приводит к снижению производительности.

Мне были бы интересны отзывы об этих подходах и любые предложения по альтернативным подходам.

Это было полезно?

Решение

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

Разные GC делают это по-разному.

Обычно копируя сборщики при обходе кучи, они не просматривают все объекты в куче.Скорее они ходят по ЖИВЫМ объектам в куче.Подразумевается, что если он доступен из «корневого» объекта, то объект активен.

Итак, на этом этапе ему в любом случае приходится касаться всех живых объектов, поскольку он копирует их из старой кучи в новую.После копирования живых объектов в старой куче остаются либо уже скопированные объекты, либо мусор.На этом этапе старую кучу можно полностью удалить.

Двумя основными преимуществами этого типа сборщика являются то, что он уплотняет кучу на этапе копирования и копирует только живые объекты.Это важно для многих систем, потому что с помощью такого типа сборщика выделение объектов обходится очень дешево, буквально немногим больше, чем увеличение указателя кучи.Когда происходит сборка мусора, ни один из «мертвых» объектов не копируется, поэтому они не замедляют работу сборщика.В динамических системах также оказывается, что мелкого временного мусора гораздо больше, чем старого мусора.

Кроме того, просматривая график живых объектов, вы можете увидеть, как сборщик мусора может «знать» о каждом объекте, и отслеживать их для любых целей корректировки адреса, выполняемых во время копирования.

Это не тот форум, где можно глубоко обсуждать механику GC, поскольку это нетривиальная проблема, но это основы работы копирующего сборщика.

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

Другие советы

(Практически) Любая система сбора мусора должна перемещать объекты в памяти, чтобы упаковать их более плотно и избежать проблем фрагментации.

То, на что вы смотрите, — это очень большая и сложная тема.Я бы посоветовал вам прочитать существующие API стиля удаленных объектов:Удаленное взаимодействие .NET и более ранние технологии, такие как КОРБА

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

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

Ответ на комментарии:

В вашем вопросе говорится о хранении объектов распределенным образом, а именно это и есть удаленное взаимодействие .NET и адрес CORBA.По общему признанию, ни одна из технологий не поддерживает миграцию этих объектов (AFAIK).Но они оба широко занимаются концепциями идентичности объектов, которые являются важной частью любой распределенной объектной системы:как разные части системы узнают, о каких объектах они говорят.

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

Однако основная идея сбора мусора заключается в следующем:

  • Виртуальная машина останавливает выполнение управляемого кода всеми потоками.
  • Он выполняет анализ достижимости на основе набора известных «корней»:статические переменные, локальные переменные во всех потоках.Для каждого найденного объекта он следует всем ссылкам внутри объекта.
  • Любой объект, не идентифицированный анализом достижимости, является мусором.
  • Объекты, которые еще живы, затем можно переместить вниз по памяти, чтобы плотно упаковать их.Это означает, что любые ссылки на эти объекты также должны быть обновлены с использованием нового адреса.Контролируя, когда может произойти сбор мусора, виртуальная машина может гарантировать отсутствие ссылок на объекты «в воздухе» (т.хранится в машинном реестре), что может вызвать проблемы.
  • После завершения процесса виртуальная машина снова запускает выполнение потоков.

В качестве усовершенствования этого процесса виртуальная машина может выполнять сборку мусора по поколениям, при которой отдельные кучи поддерживаются в зависимости от «возраста» объекта.Объекты начинаются в куче 0, и если они выдерживают несколько сборок мусора, то мигрируют в кучу 1 и, в конечном итоге, в кучу 2 (и так далее - хотя .NET поддерживает только 3 поколения).Преимущество этого заключается в том, что сборщик мусора может очень часто запускать коллекции в куче 0 и не беспокоиться о выполнении работы по доказательству того, что долгоживущие объекты (которые оказались в куче 2) все еще живы (что почти наверняка так и есть). .

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

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

Однако существует тонкая разница между тем, что предлагает Терракота, и тем, о чем вы просите, поэтому мой вопрос.

Разница в том, что, насколько вам известно, Terracotta не предоставляет «удаленных» ссылок на объекты - фактически, все «удаленное» понятие RMI, JMS и т. д.полностью отсутствует при использовании Терракоты.

Скорее, в Terracotta все объекты находятся в большой виртуальной куче.Потоки, будь то на узле 1, узле 2, узле 3, узле 4 и т. д., имеют доступ к любому объекту в виртуальной куче.

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

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

Более того, в отличие от любого предыдущего решения, ссылки на объекты сохраняются между узлами, то есть вы можете использовать ==.Все это часть поддержки модели памяти Java в кластере, что является фундаментальным требованием для создания «обычной» Java (например,POJO, синхронизированные, ожидание/уведомление) работают (ничего из этого не работает, если вы не/не можете сохранить идентичность объекта в кластере).

Итак, вам возвращается вопрос для дальнейшего уточнения ваших требований: для какой цели вам нужны «удаленные» указатели?

Ключевое слово, которое вам нужно, — «уплотняющий сборщик мусора».JVM разрешено использовать один, а это означает, что объекты можно перемещать.Обратитесь к руководству вашей JVM, чтобы узнать, работает ли ваша, и есть ли какие-либо параметры командной строки, которые на нее влияют.

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

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

Похоже, вы ищете распределенный кеш, что-то вроде терракотового или Java-кеша объектов Oracle (ранее Tangersol).

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

Это не совсем то, что вы описали, но работает очень похоже.

Вот ссылка.

http://www.jboss.org/jbosscache/

Надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top