Orien está correto, é a chamada do sistema fork () acionada por ProcessBuilder ou Runtime.exec ou outros meios da JVM executando um processo externo (por exemplo, outra JVM executando ant, um comando git, etc.).
Houve algumas postagens nas listas de discussão do Jenkins sobre isso: Não é possível executar o programa" git "... error = 12, Não é possível alocar memória
Há uma boa descrição do problema na lista de desenvolvedores do SCons: fork () + exec () vs posix_spawn ()
Há um longo relatório de bug da JVM com soluções: Use posix_spawn, não fork, no S10 para evitar o esgotamento de swap . Mas não tenho certeza se isso realmente entrou no JDK7, pois os comentários sugerem que foi o plano.
Em resumo, em sistemas semelhantes ao Unix, quando um processo (por exemplo, a JVM) precisa iniciar outro processo (por exemplo, git) é feita uma chamada de sistema para fork()
que efetivamente duplica o processo atual e toda a sua memória e outros otimizam isso com copy-on-write para que a memória não seja realmente copiada até que a criança tente gravar nela). O processo duplicado, em seguida, faz outra chamada de sistema, exec()
para iniciar o outro processo (por exemplo, git), ponto em que tudo o que copiou a memória do processo pai pode ser descartado pelo sistema operacional. Se o processo pai estiver usando grandes quantidades de memória (como tendem a fazer os processos da JVM), a chamada para fork()
poderá falhar se o sistema operacional determinar que não possui memória suficiente + permuta para manter duas cópias, mesmo se o processo filho nunca utilizará realmente essa memória copiada.
Existem várias soluções:
-
Adicione mais memória física / RAM à máquina.
-
Adicione mais espaço de troca para enganar o
fork()
, mesmo que o espaço de troca não seja estritamente necessário para nada. Esta é a solução que escolhi porque é bastante fácil adicionar um arquivo de swap, e eu não queria viver com o potencial de processos serem mortos devido à supercomprometimento. -
No Linux, ative a opção
overcommit_memory
do sistema vm ( / proc / sys / vm / overcommit_memory ). Com supercomprometimento, a chamada parafork()
sempre seria bem-sucedida e, como o processo filho não vai realmente usar essa cópia da memória, tudo estará bem. É claro que é possível que, com o overcommit, seus processos realmente tentem usar mais memória do que a disponível e sejam mortos pelo kernel. Se isso é apropriado depende dos outros usos da máquina. Máquinas de missão crítica provavelmente não devem arriscar o assassino de falta de memória. Mas um servidor de desenvolvimento interno que pode suportar algum tempo de inatividade seria um bom local para permitir a supercomprometimento. -
Altere a JVM para não usar
fork()
+exec()
, mas useposix_spawn()
quando disponível. Esta é a solução solicitada no relatório de bug da JVM acima e mencionada na lista de discussão SCons. Ele também é implementado em java_posix_spawn .Estou tentando descobrir se essa correção entrou no JDK7. Se não, gostaria de saber se o pessoal do Jenkins estaria interessado em um trabalho como o java_posix_spawn. Parece haver tentativas de integrar isso em Apache commons-exec .
Programmieraffe, não tenho 100% de certeza, mas seu link sugere que a correção está no JDK7 e no JDK6 1.6.0_23 e posterior. Para o registro, eu estava executando o OpenJDK 1.6.0_18.
Veja link