У меня есть вопрос относительно управления памятью JVM (по крайней мере, для SUN).
Я хотел бы знать, как управлять тем фактом, что JVM отправляет неиспользованную память обратно в ОС (окна в моем случае).
Я написал простую java-программу, чтобы проиллюстрировать, что я ожидаю. Запустите его с параметром -Dcom.sun.management.jmxremote, чтобы вы могли также контролировать кучу с помощью jconsole, например.
Со следующей программой:
package fr.brouillard.jvm;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
public class MemoryFree {
private BufferedReader reader = new BufferedReader(new
InputStreamReader(System.in));
private List<byte[]> usedMemory = new LinkedList<byte[]>();
private int totalMB = 0;
private int gcTimes = 0;
public void allocate(int howManyMB) {
usedMemory.add(new byte[howManyMB * 1024 * 1024]);
totalMB += howManyMB;
System.out.println(howManyMB + "MB allocated, total allocated: " +
totalMB + "MB");
}
public void free() {
usedMemory.clear();
}
public void gc() {
System.gc();
System.out.println("GC " + (++gcTimes) + " times" );
}
public void waitAnswer(String msg) {
System.out.println("Press [enter]" + ((msg==null)?"":msg));
try {
reader.readLine();
} catch (IOException e) {
}
}
public static void main(String[] args) {
MemoryFree mf = new MemoryFree();
mf.waitAnswer(" to allocate memory");
mf.allocate(20);
mf.allocate(10);
mf.allocate(15);
mf.waitAnswer(" to free memory");
mf.free();
mf.waitAnswer(" to GC");
mf.gc();
mf.waitAnswer(" to GC");
mf.gc();
mf.waitAnswer(" to GC");
mf.gc();
mf.waitAnswer(" to GC");
mf.gc();
mf.waitAnswer(" to exit the program");
try {
mf.reader.close();
} catch (IOException e) {}
}
}
Внутренняя куча свободна после завершения первого GC (что ожидается), но память возвращается только в ОС, начиная с третьего GC. После четвертого, полная выделенная память отправляется обратно в ОС.
Как настроить JVM для управления этим поведением? На самом деле, моя проблема в том, что мне нужно запустить несколько сеансов клиентов CITRIX на сервере, но я хотел бы, чтобы запущенные JVM на сервере освобождали память как можно скорее (у меня в моем приложении только несколько функций с высокой потребляемой памятью).
Если это поведение невозможно контролировать, могу ли я позволить ему это сделать и вместо этого увеличить виртуальную память ОС и позволить ОС использовать его так, как он хочет, без больших проблем с производительностью. Например, будут ли проблемы иметь 10 java-процессов в 1 ГБ памяти (с реальными выделенными объектами только 100 МБ в куче) на сервере с 4 ГБ с достаточной виртуальной памятью, конечно.
Я думаю, что другие люди уже столкнулись с такими вопросами/проблемами.
Спасибо за вашу помощь.