J'ai une collection de webapps qui fonctionnent sous tomcat. Tomcat est configuré pour avoir jusqu'à 2 Go de mémoire en utilisant l'argument -Xmx.
De nombreuses applications web doivent effectuer une tâche qui finit par faire appel au code suivant :
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
process.waitFor();
...
Le problème que nous rencontrons est lié à la manière dont ce "processus enfant" est créé sous Linux (Redhat 4.4 et Centos 5.4).
Je crois comprendre qu'une quantité de mémoire égale à celle que tomcat utilise doit être libre dans le pool de mémoire physique (non swap) du système pour que ce processus enfant puisse être créé. Lorsque nous n'avons pas assez de mémoire physique libre, nous obtenons ceci :
java.io.IOException: error=12, Cannot allocate memory
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 28 more
Mes questions sont les suivantes :
1) Est-il possible de supprimer l'exigence selon laquelle une quantité de mémoire égale au processus parent doit être libre dans la mémoire physique ? Je cherche une réponse qui me permette de spécifier combien de mémoire le processus enfant obtient ou de permettre à java sous linux d'accéder à la mémoire swap.
2) Quelles sont les alternatives à Runtime.getRuntime().exec() si aucune solution au #1 n'existe ? Je n'en ai retenu que deux, dont aucune n'est très désirable. JNI (très peu souhaitable) ou réécrire le programme que nous appelons en Java et en faire un processus propre avec lequel la webapp communique d'une manière ou d'une autre. Il doit y en avoir d'autres.
3) Y a-t-il un autre aspect de ce problème que je ne vois pas et qui pourrait potentiellement le résoudre ? Diminuer la quantité de mémoire utilisée par tomcat n'est pas une option. L'augmentation de la mémoire sur le serveur est toujours une option, mais cela semble être plus un pansement.
Les serveurs utilisent Java 6.
EDIT : Je dois préciser que je ne cherche pas un correctif spécifique à Tomcat. Ce problème peut être observé avec n'importe laquelle des applications java que nous avons sur le serveur web (il y en a plusieurs). J'ai simplement utilisé tomcat comme exemple parce qu'il aura probablement le plus de mémoire allouée et c'est là que nous avons vu l'erreur la première fois. Il s'agit d'une erreur reproductible.
EDIT : Finalement, nous avons résolu ce problème en réécrivant ce que l'appel système faisait en java. Je pense que nous avons eu beaucoup de chance de pouvoir le faire sans faire d'appels système supplémentaires. Tous les processus ne seront pas en mesure de le faire, donc j'aimerais bien voir une solution réelle à ce problème.