¿Cómo resolver “java.io.IOException: error = 12, no se puede asignar memoria” en tiempo de ejecución llamando # exec ()?

StackOverflow https://stackoverflow.com/questions/1124771

  •  13-09-2019
  •  | 
  •  

Pregunta

En mi sistema no puede ejecutar una aplicación Java simple que se inicia un proceso. No sé cómo resolver.

¿Me podría dar algunas pistas de cómo resolver?

El programa es:

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

}

El resultado es:

[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

Configuración del sistema:

[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: Solución Esto resuelve mi problema, no sé exactamente por qué:

echo 0> / proc / sys / vm / overcommit_memory

Hasta-votos para que sea capaz de explicar:)

informaciones adicionales, de salida superior:

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

informaciones adicionales, de salida 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
¿Fue útil?

Solución

¿Cuál es el perfil memoria de la máquina? p.ej. si ejecuta top, la cantidad de memoria libre tiene?

Sospecho UnixProcess realiza una fork() y simplemente no está recibiendo suficiente memoria desde el sistema operativo (si mal no recuerdo, que va a fork() para duplicar el proceso y luego exec() para ejecutar el comando ls en el nuevo proceso de la memoria, y no es obtener la mayor la medida de lo que)

EDIT: Re. su solución overcommit, permite La sobrecarga de la memoria del sistema, posiblemente permitiendo que los procesos para asignar (pero no utilizan) más memoria que está realmente disponible. Así que supongo que la fork() duplica la memoria del proceso de Java como se explica en los comentarios a continuación. Por supuesto que no utiliza la memoria, ya que los 'ls' reemplaza el proceso de Java duplicado.

Otros consejos

Esta es la solución, pero hay que establecer:

echo 1 > /proc/sys/vm/overcommit_memory

Esto se resuelve en la versión de Java 1.6.0_23 y hacia arriba.

Vea más detalles en http://bugs.sun.com/bugdatabase/view_bug.do?bug_id = 7034935

Runtime.getRuntime().exec asigna el proceso con la misma cantidad de memoria como el principal. Si usted tuviera que establecer Montón de 1 GB y tratar de exec entonces se asignará otra 1GB para ese proceso a ejecutar.

Me encontré con estos enlaces:

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

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

Parece ser un error. Se recomienda el uso de un engendro () en lugar de engañar a la llanura tenedor () / exec ().

Me resolvieron este usando 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 nos fijamos en la fuente de java.lang.Runtime, verá finalmente exec llamada al método protegido: execVM, lo que significa que utiliza la memoria virtual. Así que para el sistema Unix, VM depende de la cantidad de espacio de intercambio + alguna relación de la memoria física.

respuesta

de Michael no soluciona el problema, pero podría (o decir, con el tiempo) que el uno mismo punto muerto en cuestión de la asignación de memoria desde el 1 de uno mismo digo menos cuidadoso de asignación de memoria y 0 es sólo una suposición y, obviamente, que son la suerte de que uno mismo supongo que puede tener la memoria ESTE MOMENTO. ¿La próxima vez? Hmm .....

Una mejor aproximación es que pruebe su caso y darle un buen espacio de intercambio y da una mejor relación entre la memoria física utilizada y establecer el valor a 2 en lugar de 1 o 0.

overcommit_memory

Controles overcommit de memoria del sistema, posiblemente permitiendo procesos para asignar (pero no utilizan) más memoria que está realmente disponible.

0 - manejo overcommit heurístico. overcommits obvias de espacio de direcciones se negaron. Se utiliza para un sistema típico. Se asegura una asignación serio salvaje falla al tiempo que permite overcommit para reducir el uso de intercambio. se permite la raíz de asignar ligeramente más memoria en este modo. Este es el valor predeterminado.

1 - Siempre overcommit. Apropiada para algunas aplicaciones científicas.

2 - No overcommit. El espacio total de direcciones comprometerse para el sistema no se le permite exceder de intercambio más un porcentaje configurable (por defecto es 50) de memoria RAM física. Dependiendo del porcentaje que utiliza, en la mayoría de las situaciones, esto significa un proceso que no se mató al intentar utilizar memoria asignada ya, pero recibirá errores en la asignación de memoria en su caso.

Puede utilizar el contenedor Tanuki a generar un proceso con POSIX desove en lugar de tenedor. http://wrapper.tanukisoftware.com/doc/english/child-exec.html

  

El WrapperManager.exec () función es una alternativa a la Java-Runtime.exec (), que tiene la desventaja de utilizar el método de tenedor (), que puede convertirse en algunas plataformas muy memoria caros para crear un nuevo proceso.

Por extraño que esto pueda parecer, una solución es reducir la cantidad de memoria asignada a la máquina virtual Java. Desde tenedor () duplica el proceso y su memoria, si su proceso de JVM no necesita realmente más memoria que se asigna a través de -Xmx, la asignación de memoria a Git va a funcionar.

Por supuesto, puede probar otras soluciones mencionadas aquí (como exceso de la comisión o actualizar a una JVM que tiene el punto de referencia). Usted puede tratar de reducir la memoria si estás desesperado por una solución que mantiene intacto todo el software sin ningún impacto ambiental. También hay que tener en cuenta que la reducción de -Xmx agresiva puede causar Ooms. Me gustaría recomendar la actualización del JDK como una solución estable a largo plazo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top