Назад | Перейти на главную страницу

когда куча jvm выделена ОС

Одна из наших систем sap (стек PI ABAP + JAVA) давала проблемы с производительностью. Все 64 ГБ, сконфигурированные для машины, загружаются (и 8 ядер тоже). Все подозревают java-часть, но я думаю иначе.

Узлы java-сервера, которые перезагружались с ошибкой Out Of Memory. Глядя на файлы hprof, я обнаружил, что они имеют размер всего 1,2 ГБ (в среднем из 3 узлов сервера), когда для узлов сервера настроено 3 ГБ (как -Xms, так и Xmx) кучи. Это наблюдение вызывает следующее сомнение.

Я читал, что когда для Xms и Xmx установлено одно и то же значение, jvm выделяет всю кучу при запуске. В этом случае серверные узлы с самого начала будут иметь 3 ГБ кучи. Если да, то почему это не отражается в файле hprof или если hprof содержит только память, выделенную для объектов во время выполнения, размер явно указывает на то, что память кучи была свободна (более 50%), так как ошибка OOM. .. !! .. ??

Я также знаю, что Linux делает что-то, что называется чрезмерной фиксацией памяти. т.е. память фактически предоставляется не тогда, когда она запрашивается, а когда она фактически используется. Способствует ли это исключению нехватки памяти. Например, при запуске JVM операционная система сообщает ей, что вам было выделено 3 ГБ памяти, но фактически откладывает ее до тех пор, пока она действительно не понадобится. К тому времени, когда jvm фактически попытается выделить память объектам, некоторые другие приложения могут исчерпать память. Это возможно...??

Даже если бы у java-узлов была проблема с утечкой памяти, разве это не было бы ограничено 3 ГБ кучи. Как он может забрать все 64 ГБ физической памяти .... ???

Еще я заметил, что пространство подкачки использовалось только на 50%.

Любой свет на это ...!

SAP OSS также занимался этим вопросом. Сегодня получил от них ответ. Мое наблюдение было правильным. Ява не была виновата. Стек ABAP столкнулся с некоторой проблемой и не освободил память. После перезапуска рабочего процесса ABAP память освободилась на уровне ОС.

Но я также хотел бы понять выделенную часть вопроса, например, может ли такая ситуация возникнуть или нет, приводя к ошибкам JAVA OOM ... ?? .. !!. Любая информация по этому поводу будет полезна.

Overcommit по умолчанию включен в Linux в эвристическом режиме. Это означает, что ядро ​​обычно допускает чрезмерную фиксацию - это означает, что пообещает больше памяти всем процессам, запрашивающим его, чем оно фактически может доставить, в надежде, что процессы никогда не начнут использовать всю память одновременно. Возможно, на вашем сервере отключен overcommit, вы можете проверить это, запустив:

$ cat /proc/sys/vm/overcommit_memory

Если значение равно 0, включена эвристическая избыточная фиксация.

Если возникает ситуация, когда фактическое использование памяти превышает объем оперативной памяти, который может предоставить система, ядро ​​активирует OOM killer, который пытается убить процессы, чтобы освободить память. Обычно он убивает самые молодые процессы, потребляющие большие объемы оперативной памяти, но вы не можете на это полагаться. Это может (и будет) вызвать хаос. Вы можете изменить сродство OOM, чтобы убить определенные процессы, отрегулировав / proc // oom_adj (например, если вы хотите избежать ситуации, когда OOM убивает базу данных или какого-либо другого пользователя большой RAM [ab]).

Итак, если ваша система входит в фазу OOM, последствия для процессов Java могут заключаться в том, что они будут мгновенно завершены, что не приведет к появлению сообщений «Out of memory» в журналах Java, которые вы наблюдаете.

Установка одного и того же значения для Xmx и Xms предотвратит изменение размера кучи, но это не означает, что java-процесс начнет использовать всю память сразу при запуске. Он будет выделять столько, сколько ему требуется памяти VIRT, но резидентный набор данных не вырастет до Xms, а останется настолько низким, насколько это необходимо.

Что касается виртуальной памяти: ядро ​​обещает (сверхкоммитирует) Java-процессу столько, сколько он запрашивает (Xmx + некоторые дополнительные), но вся эта память не будет выделена немедленно. Будет выделена только сумма, необходимая для текущих данных, и вы можете увидеть, сколько ее, наблюдая за размером резидентного набора (физическая память без подкачки, которую использовала задача). Чтобы увидеть размеры VIRT и RSS, вы можете выполнить следующую команду:

$ ps aux | egrep '(^USER|java)'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tomcat   10229 21.5  9.1 6813688 548344 ?      Sl   09:01   1:10 ....java...

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