web-dev-qa-db-fra.com

Comment résoudre "Java.io.IOException: error = 12, impossible d'allouer de la mémoire" en appelant Runtime # exec ()?

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
66
Andrea Francia

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.

18
Brian Agnew

C'est la solution mais vous devez définir:

echo 1 > /proc/sys/vm/overcommit_memory
36
Michael

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

9
Alf Høgemark

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.

9
Attila Bukta

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 ().

8
akarnokd

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");
    }
}
8
kongo09

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.

5
Scott Chu

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.

4
Dan Fabulich

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.

4
Deepak Bala

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.

4
ricardofunke