Sur mon système, je ne peux pas exécuter une simple Java qui démarre un processus. Je ne sais pas comment résoudre le problème.
Pourriez-vous me donner quelques astuces comment résoudre?
Le programme est:
[root@newton sisma-acquirer]# cat prova.Java
import Java.io.IOException;
public class prova {
public static void main(String[] args) throws IOException {
Runtime.getRuntime().exec("ls");
}
}
Le résultat est:
[root@newton sisma-acquirer]# javac prova.Java && Java -cp . prova
Exception in thread "main" Java.io.IOException: Cannot run program "ls": Java.io.IOException: error=12, Cannot allocate memory
at Java.lang.ProcessBuilder.start(ProcessBuilder.Java:474)
at Java.lang.Runtime.exec(Runtime.Java:610)
at Java.lang.Runtime.exec(Runtime.Java:448)
at Java.lang.Runtime.exec(Runtime.Java:345)
at prova.main(prova.Java:6)
Caused by: Java.io.IOException: Java.io.IOException: error=12, Cannot allocate memory
at Java.lang.UNIXProcess.<init>(UNIXProcess.Java:164)
at Java.lang.ProcessImpl.start(ProcessImpl.Java:81)
at Java.lang.ProcessBuilder.start(ProcessBuilder.Java:467)
... 4 more
Configuration du système:
[root@newton sisma-acquirer]# Java -version
Java version "1.6.0_0"
OpenJDK Runtime Environment (IcedTea6 1.5) (Fedora-18.b16.fc10-i386)
OpenJDK Client VM (build 14.0-b15, mixed mode)
[root@newton sisma-acquirer]# cat /etc/Fedora-release
Fedora release 10 (Cambridge)
EDIT: Solution Ceci résout mon problème, je ne sais pas exactement pourquoi:
echo 0>/proc/sys/vm/oversommit_memory
Up-votes pour qui est capable d'expliquer :)
Informations complémentaires, top output:
top - 13:35:38 up 40 min, 2 users, load average: 0.43, 0.19, 0.12
Tasks: 129 total, 1 running, 128 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.5%us, 0.5%sy, 0.0%ni, 94.8%id, 3.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1033456k total, 587672k used, 445784k free, 51672k buffers
Swap: 2031608k total, 0k used, 2031608k free, 188108k cached
Informations complémentaires, sortie libre:
[root@newton sisma-acquirer]# free
total used free shared buffers cached
Mem: 1033456 588548 444908 0 51704 188292
-/+ buffers/cache: 348552 684904
Swap: 2031608 0 2031608
Quel est le profil de mémoire de votre machine? par exemple. si vous utilisez top
, combien de mémoire libre avez-vous?
Je soupçonne que UnixProcess
effectue une fork()
et qu’elle ne récupère tout simplement pas assez de mémoire de l’OS (si la mémoire est utilisée, il va fork()
pour dupliquer le processus, puis exec()
pour exécuter le ls dans le nouveau processus de mémoire, et ça ne va pas aussi loin que ça)
EDIT: Re. votre solution sur-engagée, elle permet de surcharger la mémoire système, en permettant éventuellement aux processus d’allouer (sans utiliser) plus de mémoire que ce qui est réellement disponible. Je suppose donc que la fork()
duplique la mémoire de processus Java), comme indiqué dans les commentaires ci-dessous. Bien sûr, vous n'utilisez pas la mémoire car le "ls" remplace le duplicata. Java processus.
C'est la solution mais vous devez définir:
echo 1 > /proc/sys/vm/overcommit_memory
Ceci est résolu dans Java version 1.6.0_23 et ultérieure.
Voir plus de détails sur http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=7034935
Runtime.getRuntime().exec
alloue le processus avec la même quantité de mémoire que le processus principal. Si vous avez défini heap sur 1 Go et que vous essayez d'exécuter, il allouera 1 Go supplémentaire pour l'exécution de ce processus.
Je suis tombé sur ces liens:
http://mail.openjdk.Java.net/pipermail/core-libs-dev/2009-May/001689.html
http://www.nabble.com/Review-request-for-5049299-td23667680.html
Semble être un bug. Il est conseillé d’utiliser une astuce spawn () au lieu d’un simple fork ()/exec ().
J'ai résolu ceci en utilisant la JNA: https://github.com/twall/jna
import com.Sun.jna.Library;
import com.Sun.jna.Native;
import com.Sun.jna.Platform;
public class prova {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
int system(String cmd);
}
private static int exec(String command) {
return CLibrary.INSTANCE.system(command);
}
public static void main(String[] args) {
exec("ls");
}
}
Si vous examinez la source de Java.lang.Runtime, vous verrez que exec a finalement appelé la méthode protégée: execVM, ce qui signifie qu'il utilise la mémoire virtuelle. Ainsi, pour les systèmes de type Unix, VM dépend de la quantité d’espace de permutation + un certain ratio de mémoire physique.
La réponse de Michael a résolu votre problème, mais elle pourrait (ou pourrait éventuellement dire) causer le problème impasse dans le problème d'allocation de mémoire depuis 1 dire à O.S. Moins de soin de l'allocation de mémoire et 0 est juste de deviner & évidemment que vous avez de la chance que O.S. suppose que tu peux avoir de la mémoire CETTE FOIS. La prochaine fois? Hmm .....
Une meilleure approche consiste à expérimenter votre cas et à donner un bon espace d’échange et un meilleur ratio mémoire physique utilisée et définir la valeur sur 2 au lieu de 1 ou 0.
Vous pouvez utiliser l'encapsuleur Tanuki pour générer un processus avec spawn POSIX au lieu de fork. http://wrapper.tanukisoftware.com/doc/english/child-exec.html
La fonction WrapperManager.exec () est une alternative à Java-Runtime.exec () qui présente l'inconvénient d'utiliser la méthode fork (), qui peut devenir très coûteuse en mémoire pour créer un nouveau processus.
Aussi étrange que cela puisse paraître, il convient de réduire la quantité de mémoire allouée à la machine virtuelle. Fork () dupliquant le processus et sa mémoire, si votre processus JVM n'a pas vraiment besoin de la mémoire allouée via -Xmx, l'allocation de mémoire à git fonctionnera.
Bien sûr, vous pouvez essayer d'autres solutions mentionnées ici (telles que la sur-validation ou la mise à niveau vers une machine virtuelle qui dispose du correctif). Vous pouvez essayer de réduire la mémoire si vous recherchez une solution qui préserve tous les logiciels, sans impact sur l’environnement. N'oubliez pas non plus qu'une réduction agressive de -Xmx peut provoquer des MOO. Je recommanderais de mettre à niveau le JDK en tant que solution stable à long terme.
surcommit_memory
Contrôle les surcharges de mémoire système, permettant éventuellement aux processus d'allouer (mais pas d'utiliser) plus de mémoire que ce qui est réellement disponible.
0 - Traitement par excès d'heuristique. Les surcharges évidentes d'espace d'adressage sont refusées. Utilisé pour un système typique. Cela garantit une allocation sérieusement sauvage, tout en permettant à un surengagement de réduire l'utilisation de swap. root est autorisé à allouer un peu plus de mémoire dans ce mode. C'est la valeur par défaut.
1 - Toujours trop engagé. Convient à certaines applications scientifiques.
2 - Ne pas trop engager. La validation de l'espace d'adressage total pour le système ne doit pas dépasser swap plus un pourcentage configurable (50 par défaut) de RAM physique. Selon le pourcentage que vous utilisez, dans la plupart des situations, cela signifie qu'un processus ne sera pas tué lors de la tentative d'utilisation de la mémoire déjà allouée, mais qu'il recevra des erreurs d'allocation de mémoire, le cas échéant.