В вашем случае решения чисто на java нет. Здесь необходимо зарядить регулярную задачу (cron), которая будет смотреть свободную физическую память в системе и убивать самое толстое java приложение при достижении 95% лимита памяти. Например, так:
#!/usr/bin/env bash
# pid'ы отслеживаемых java процессов
# задачку определения актуальных pid'ов оставлю на вас
PID1=1234
PID2=5678
# минимальное допустимое количество свободной памяти в процентах
MIN_MEM_SIZE=5
function get_java_mem {
jstat -gc $1 | awk 'NR==1 {print ($3 + $4 + $6 + $8 + $10)}'
}
function get_free_mem {
free | awk 'NR==2 {print ($7 * 100) / $2}'
}
if [ $(echo "`get_free_mem` < $MIN_MEM_SIZE" | bc) -eq "1" ]; then
if [ $(echo "`get_java_mem $PID1` > `get_java_mem $PID2`" | bc) -eq "1" ]; then
PID_TO_KILL=$PID1;
else
PID_TO_KILL=$PID2
fi
echo "Memory shortage detected. Taking heap dump and killing process $PID_TO_KILL"
jmap -dump:format=b,file=${PID_TO_KILL}.heapdump.bin $PID_TO_KILL
kill $PID_TO_KILL
fi
если я пропишу -Xmx2g то оба влезут, но если один процесс использует все 2 гб, то второй не может эту память использовать.
Не очень ясно зачем нужны такие качели. Если приложение нормально работает с -Xmx2g, то с -Xmx4g сильно лучше не станет. Разве что full gc будет происходить немного чаще, только и всего.