Nous avons une longue durée de vie des processus de serveur, que rarement besoin de beaucoup de RAM pour un court moment. Nous voyons qu'une fois que la JVM a obtenu la mémoire de l'OS, il ne retourne jamais en arrière de l'OS. Comment pouvons-nous demander à la JVM de retour de segment de mémoire pour le système d'exploitation?
Généralement, la accepté de répondre à de telles questions est d'utiliser
-XX:MaxHeapFreeRatio
et -XX:MinHeapFreeRatio
. (Voir par ex.
1,2,3,4). Mais nous sommes en cours d'exécution java comme ceci:
java -Xmx4G -XX:MaxHeapFreeRatio=50 -XX:MinHeapFreeRatio=30 MemoryUsage
et encore le voir dans VisualVM:
Clairement, la JVM est de ne pas honorer -XX:MaxHeapFreeRatio=50
comme le heapFreeRatio est très proche de 100% et nulle part près de 50%. Aucun montant de cliquer sur "Effectuer GC" les retours de la mémoire pour le système d'exploitation.
MemoryUsage.java:
import java.util.ArrayList;
import java.util.List;
public class MemoryUsage {
public static void main(String[] args) throws InterruptedException {
System.out.println("Sleeping before allocating memory");
Thread.sleep(10*1000);
System.out.println("Allocating/growing memory");
List<Long> list = new ArrayList<>();
// Experimentally determined factor. This gives approximately 1750 MB
// memory in our installation.
long realGrowN = 166608000; //
for (int i = 0 ; i < realGrowN ; i++) {
list.add(23L);
}
System.out.println("Memory allocated/grown - sleeping before Garbage collecting");
Thread.sleep(10*1000);
list = null;
System.gc();
System.out.println("Garbage collected - sleeping forever");
while (true) {
Thread.sleep(1*1000);
}
}
}
Versions:
> java -version
openjdk version "1.8.0_66-internal"
OpenJDK Runtime Environment (build 1.8.0_66-internal-b01)
OpenJDK 64-Bit Server VM (build 25.66-b01, mixed mode)
> uname -a
Linux londo 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u5 (2015-10-09) x86_64 GNU/Linux
> lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.2 (jessie)
Release: 8.2
Codename: jessie
J'ai aussi essayé de OpenJDK 1.7 et Sun Java 1.8. Tous se comportent de la même manière et aucun donner de la mémoire au système d'exploitation.
Je ne pense que j'ai besoin et ce que le swap et la pagination ne sera pas "résoudre" ce, parce que les dépenses d'e / s disque sur la pagination près de 2 go de déchets à l'intérieur est juste un gaspillage de ressources. Si vous êtes en désaccord, merci de m'éclairer.
J'ai également écrit un petit memoryUsage.c avec malloc()
/free()
, et il n' retour de la mémoire pour le système d'exploitation. Il est possible en C. peut-être pas avec Java?
Edit: Augusto a souligné que la recherche aurait m'a conduit à l' -XX:MaxHeapFreeRatio
et -XX:MinHeapFreeRatio
seulement travaillé avec -XX:+UseSerialGC
. J'étais fou de joie et il a essayé, intrigué par le fait que je n'avais pas trouvé moi-même. Oui, il a fait un travail avec mon MemoryUsage.java:
Cependant, lorsque j'ai essayé d' -XX:+UseSerialGC
avec notre application réelle, pas tellement:
J'ai découvert que gc() après un certain temps, a l'aide, j'ai donc fait un thread qui n'a plus ou moins:
while (idle() && memoryTooLarge() && ! tooManyAttemptsYet()) {
Thread.sleep(10*1000);
System.gc();
}
et qui a fait le tour:
En fait, j'avais déjà vu le comportement avec -XX:+UseSerialGC
et de multiples System.gc()
des appels dans certains de mes nombreuses expériences, mais n'aimait pas la nécessité d'un GC fil. Et qui sait si ça va continuer à travailler comme notre application mobile et java évolue. Il doit y avoir une meilleure façon.
Quelle est la logique qui m'oblige à appeler System.gc()
quatre fois (mais pas immédiatement), et où est ce genre de choses-ils documentés?
À la recherche de la documentation pour -XX:MaxHeapFreeRatio
et -XX:MinHeapFreeRatio
travaillant uniquement avec des -XX:+UseSerialGC
, j'ai lu la documentation de l'outil java/exécutable et il n'est pas mentionné nulle part qu' -XX:MaxHeapFreeRatio
et -XX:MinHeapFreeRatio
ne fonctionne qu'avec des -XX:+UseSerialGC
. En fait, la résolution d'un problème [JDK-8028391] Faire le Min/MaxHeapFreeRatio drapeaux gérable dit:
Afin de permettre aux applications de contrôler quand et comment pour permettre plus ou moins de GC, les drapeaux-XX:MinHeapFreeRatio et -XX:MaxHeapFreeRatio doit être faite gérable. Soutien pour ces indicateurs doivent également être mis en œuvre dans le par défaut parallèle collector.
Un commentaire pour la correction d'un problème dit:
Soutien pour ces indicateurs ont également été ajoutés à la ParallelGC comme le cadre de l'adaptation de la taille politique.
J'ai vérifié, et le correctif référencé dans la résolution d'un problème réalignés pour openjdk-8 est en effet contenue dans le paquet source archive pour la openjdk-8 version que j'utilise. Il devrait donc apparemment le travail en "par défaut parallèle collector", mais n'est pas, comme je l'ai démontré dans ce post. Je n'ai pas encore trouvé aucune documentation qui dit qu'elle doit fonctionner uniquement avec -XX:+UseSerialGC
. Et comme je l'ai indiqué ici, même cela n'est pas fiable ou risquée.
Je ne peux pas juste obtenir -XX:MaxHeapFreeRatio
et -XX:MinHeapFreeRatio
à faire ce qu'ils promettent, sans avoir à passer par toutes ces paniers?