Перемещает ли Java VM объекты в памяти, и если да, то как? - PullRequest
14 голосов
/ 18 сентября 2008

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

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

Мои две идеи:

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

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

Ответы [ 6 ]

11 голосов
/ 18 сентября 2008

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

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

Обычно копируя коллекторы, когда они идут по куче, они не обходят все объекты в куче. Скорее они ходят в кучу живых объектов. Подразумевается, что если это достижимо от «корневого» объекта, объект является живым.

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

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

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

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

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

3 голосов
/ 30 сентября 2008

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

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

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

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

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

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

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

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

3 голосов
/ 18 сентября 2008

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

То, на что вы смотрите, является очень большим и сложным предметом. Я бы посоветовал вам ознакомиться с существующими API-интерфейсами в стиле удаленных объектов: удаленное взаимодействие с .NET и вернуться к таким технологиям, как CORBA

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

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

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

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

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

Тем не менее, основная идея для сборки мусора такова:

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

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

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

2 голосов
/ 18 сентября 2008

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

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

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

1 голос
/ 18 сентября 2008

звучит так, как будто вы ищете распределенный кеш, что-то вроде терракоты или java objece cache (ранее тангерсол).

0 голосов
/ 30 сентября 2008

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

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

Вот ссылка.

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

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

...