Есть ли способ заставить JVM использовать своп независимо от того, насколько велика потребность в памяти? - PullRequest
14 голосов
/ 03 января 2011

Вот моя ситуация: у меня есть задача, которая требует много памяти. Мне не хватает оперативной памяти, и независимо от того, что я пробовал (Jrockit с ключом / 3gb и т. Д.), Я не могу дать достаточно памяти JVM, и операция завершается с исключением, сообщая мне, что мне нужно больше места в куче.

Можно ли как-нибудь заставить JVM использовать механизм подкачки ОС, чтобы он не исчерпал память? Это Windows XP 32 бит

Это заняло бы целую вечность, но мне было бы все равно, мне просто нужно, чтобы эта операция была завершена.

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

Это обязательное редактирование, поскольку я получаю одинаковый ответ почти от всех :) Это не мой код Кто-то написал инструмент, который читает XML-файл в хранилище. Инструмент использует EMF и загружает всю модель одновременно. Все, что я могу сделать, это кормить его XML-файлом. В случае встроенного кода, работающего под Windows или Linux и т. Д., ОС предоставляет ему память, используя виртуальную память / пространство подкачки, и приложение не знает об этом. Мне было интересно, можно ли сделать то же самое с JVM. В 32-битной Windows -Xmx может доходить до определенной суммы, но этого недостаточно. Выйти и купить новое оборудование на данный момент не вариант для меня. Поэтому мне было интересно, можно ли заставить JVM работать как родные процессы. Медленно, но все еще работает. Видимо, это невозможно, и мне не повезло. Мне просто нужно знать, действительно ли у меня нет выбора.

Ответы [ 4 ]

10 голосов
/ 03 января 2011

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

Идея состоит в том, чтобы использовать прямые ByteBuffer s для хранения данных ваших объектов. Поскольку содержимое прямых байтовых буферов хранится в собственной памяти процесса (в отличие от кучи), вы можете положиться на механизм подкачки ОС, чтобы выгрузить память за вас. Я нашел это на этом веб-сайте (поищите «прямой байтовый буфер» на странице).

Вот как вы можете это реализовать (java-pseudo-code'ish):

class NativeMemoryCache{
  private Map<Object, ByteBuffer> data = new HashMap<...>();

  public void put(Object key, Serializable object){
    byte[] bytes = serialize(object);
    //allocate native memory to store our object
    ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
    buf.put(bytes);
    buf.flip();
    data.put(key, buf);
  }

  public Object get(Object key){
    ByteBuffer buf = data.get(key).duplicate();
    byte[] bytes = new byte[buf.remaining()];
    buf.get(bytes);
    return deserialize(bytes);
  }

  private byte[] serialize(Object obj){ ... }
  private Object deserialize(byte[] bytes){ ... }
}

Надеюсь, вы поняли идею. Вам просто нужно реализовать сериализацию (вы также можете сжимать ваши объекты с помощью zip. Это будет эффективно, если у вас есть несколько больших объектов, особенно тех, которые содержат zippable данные, такие как строки).

Конечно, NativeMemoryCache объект, data карта хешей и key s будут в куче, но это не должно занимать много памяти.

8 голосов
/ 03 января 2011

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

Однако есть предел того, насколько высоко вы можете подняться.В 32-битной системе это, вероятно, будет 2 ГБ, может быть 3 или 4 ГБ, если JVM его поддерживает.Для Sun JVM ограничение составляет 1500 МБ в 32-битной Windows, в соответствии с Java -Xmx, Макс. Память в системе .

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

Если вы пробовали максимально возможное значение, и до сих порполучить ошибки OOM, тогда единственные варианты:

  • исправить приложение так, чтобы ему требовалось меньше оперативной памяти

или

  • переместить его в64-битная ОС и увеличение -Xmx еще больше

Редактировать:

Обратите внимание, что ограничение в 4 ГиБ является ограничением архитектуры процессора , так что это относится к любому процессу, Java или нет.Так что даже нативные приемы размещения вам здесь не помогут.Единственный способ обойти это - использовать более одного процесса, но это потребует фундаментальной переписки приложения, что, вероятно, будет столь же сложным, как и просто установка приложения на использование меньшего количества оперативной памяти.Таким образом, два указанных выше варианта являются вашими единственными (разумными) вариантами.

Редактировать 2:

Чтобы ответить на новую часть вашего вопроса:

Мне было интересно, можно ли заставить JVM работать как собственные процессы.

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

Причина, по которой куча не может расти бесконечно, не в том, чтоона не может быть больше физической ОЗУ (возможно, я пробовал это по крайней мере в Linux / x86), но каждый процесс ОС (то есть, JVM) не может получить больше 4 ГБ ОЗУ.Таким образом, в 32-битных системах никогда не может быть больше, чем 4 ГБ кучи.На практике это может быть намного меньше, потому что память кучи не должна быть фрагментирована (см., Например, Максимальная память Java в Windows XP ), но 4 ГБ - это жесткий, неизбежный предел.

3 голосов
/ 03 января 2011

Согласно моему опыту, JVM запрашивает память у ОС, которая может выделить ее в оперативной памяти подкачкой.Это зависит от того, сколько у вас ресурсов.Память, которую вы можете выделить в java, зависит не от вашей оперативной памяти, а от параметра командной строки -Xmx, который вы указываете при запуске JVM.Если, например, недостаточно памяти в оперативной памяти, JVM получает ее из раздела подкачки и (я считаю) даже не знает об этом.

Кстати, ИМХО, вам действительно не нужно столько памяти.Я согласен с парнями, которые говорили это.Я бы посоветовал вам пересмотреть свой дизайн.

0 голосов
/ 03 января 2011

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

Я подозреваю, что у вас проблема в том, что вы не можете выделить достаточно непрерывной памяти, что является требованием для JVM.Поскольку вы используете больше доступной памяти, становится все труднее получить большой непрерывный блок памяти с 32-разрядной ОС.

Пришло время получить больше памяти, что в наши дни относительно дешево.или уменьшите ваши требования к памяти.Использование свопа займет у вас вечность.

Кстати: вы можете купить сервер на 24 ГБ за 1800 фунтов стерлингов и сервер на 64 ГБ за 4200 фунтов стерлингов.За £ 53 000 вы можете получить сервер с 1 ТБ памяти!: D

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