Hoe los ik “java.io.IOException: error=12, kan geen geheugen toe” op door Runtime#exec() aan te roepen?

Op mijn systeem kan ik geen eenvoudige Java-toepassing uitvoeren die een proces start. Ik weet niet hoe ik het moet oplossen.

Kun je me wat hints geven om het op te lossen?

Het programma is:

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

Het resultaat is:

[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

Configuratie van het systeem:

[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)

BEWERKEN: Oplossing
Dit lost mijn probleem op, ik weet niet precies waarom:

echo 0 > /proc/sys/vm/overcommit_memory

Up-votes voor wie het kan uitleggen 🙂

Aanvullende informatie, hoogste 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

Aanvullende informatie, gratis uitvoer:

[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

Antwoord 1, autoriteit 100%

Dit is de oplossing, maar je moet het volgende instellen:

echo 1 > /proc/sys/vm/overcommit_memory

Antwoord 2, autoriteit 57%

Wat is het geheugenprofiel van uw machine? bijv. als u topuitvoert, hoeveel vrij geheugen heeft u dan?

Ik vermoed dat UnixProcesseen fork()uitvoert en dat het gewoon niet genoeg geheugen van het besturingssysteem krijgt (als het geheugen voldoende is, zal het fork()om het proces te dupliceren en vervolgens exec()om de ls in het nieuwe geheugenproces uit te voeren, en zo ver komt het niet)

BEWERKEN: Re. uw overcommit-oplossing, maakt het overcommit van systeemgeheugen mogelijk, waardoor processen mogelijk meer geheugen kunnen toewijzen (maar niet gebruiken) dan daadwerkelijk beschikbaar is. Dus ik vermoed dat de fork()het Java-procesgeheugen dupliceert, zoals besproken in de opmerkingen hieronder. Natuurlijk gebruik je het geheugen niet omdat de ‘ls’ het dubbele Java-proces vervangt.


Antwoord 3, autoriteit 24%

Dit is opgelost in Java versie 1.6.0_23 en hoger.

Bekijk meer details op http://bugs.sun.com/bugdatabase/view_bug.do?bug_id =7034935


Antwoord 4, autoriteit 24%

Runtime.getRuntime().execwijst het proces dezelfde hoeveelheid geheugen toe als het hoofdproces. Als je heap had ingesteld op 1 GB en probeert uit te voeren, dan zal het nog eens 1 GB toewijzen om dat proces uit te voeren.


Antwoord 5, autoriteit 22%

Ik kwam deze links tegen:

http://mail.openjdk. java.net/pipermail/core-libs-dev/2009-May/001689.html

http://www.nabble.com/Review-request- for-5049299-td23667680.html

Het lijkt een bug te zijn. Het gebruik van een spawn()-truc in plaats van de gewone fork()/exec() wordt aangeraden.


Antwoord 6, autoriteit 22%

Ik heb dit opgelost met 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");
    }
}

Antwoord 7, autoriteit 14%

Als je de bron van java.lang.Runtime bekijkt, zul je zien dat exec eindelijk de beschermde methode aanroept: execVM, wat betekent dat het virtueel geheugen gebruikt. Dus voor een Unix-achtig systeem hangt VM af van de hoeveelheid swapruimte + een bepaalde verhouding van fysiek geheugen.

Michaels antwoord loste je probleem op, maar het zou (of zou uiteindelijk) ervoor kunnen zorgen dat de O.S. impasse in geheugentoewijzingsprobleem sinds 1 vertel O.S. minder voorzichtig met geheugentoewijzing & 0 is gewoon gissen & duidelijk dat je geluk hebt dat O.S. denk dat je DEZE KEER geheugen kunt hebben. De volgende keer? Hmm…..

Een betere benadering is dat u uw zaak experimenteert & geef een goede swap-ruimte & geven een betere verhouding van fysiek geheugen gebruikt & stel de waarde in op 2 in plaats van 1 of 0.


Antwoord 8, autoriteit 11%

overcommit_memory

Controleert overbelasting van systeemgeheugen, waardoor processen mogelijk meer geheugen kunnen toewijzen (maar niet gebruiken) dan er daadwerkelijk beschikbaar is.

0 – Heuristische afhandeling van overcommit. Voor de hand liggende overcommits van adresruimte worden geweigerd. Gebruikt voor een typisch systeem. Het zorgt ervoor dat een serieus wilde toewijzing mislukt, terwijl overcommit mogelijk is om het swapgebruik te verminderen. root mag in deze modus iets meer geheugen toewijzen. Dit is de standaardinstelling.

1 – Overcommit altijd. Geschikt voor sommige wetenschappelijke toepassingen.

2 – Overdrijf niet. De totale vastlegging van de adresruimte voor het systeem mag niet groter zijn dan swap plus een configureerbaar percentage (standaard is 50) fysiek RAM. Afhankelijk van het percentage dat u gebruikt, betekent dit in de meeste situaties dat een proces niet wordt afgebroken tijdens een poging om reeds toegewezen geheugen te gebruiken, maar dat er indien nodig fouten worden ontvangen bij de geheugentoewijzing.


Antwoord 9, autoriteit 11%

Je kunt de Tanuki-wrapper gebruiken om een ​​proces te spawnen met POSIX-spawn in plaats van fork. http://wrapper.tanukisoftware.com/doc/english/child-exec.html

De WrapperManager.exec()-functie is een alternatief voor de Java-Runtime.exec() die het nadeel heeft om de fork() methode te gebruiken, die op sommige platforms erg duur kan worden om een ​​nieuw proces te creëren.


Antwoord 10, autoriteit 11%

Hoe raar dit ook mag klinken, een oplossing is om de hoeveelheid geheugen die aan de JVM is toegewezen te verminderen. Aangezien fork() het proces en zijn geheugen dupliceert, zal de geheugentoewijzing aan git werken als je JVM-proces niet echt zoveel geheugen nodig heeft als is toegewezen via -Xmx.

Natuurlijk kunt u andere oplossingen proberen die hier worden genoemd (zoals te veel vastleggen of upgraden naar een JVM die de oplossing heeft). U kunt proberen het geheugen te verminderen als u wanhopig op zoek bent naar een oplossing die alle software intact houdt zonder impact op het milieu. Houd er ook rekening mee dat het agressief verminderen van -Xmx OOM’s kan veroorzaken. Ik raad aan om de JDK te upgraden als een stabiele oplossing voor de lange termijn.

Other episodes