Jenkins CI - Não é possível alocar memória

8

Eu testei o jenkins-ci com sucesso em um Ubuntu 10.4 (com vmware fusion) no meu computador local. Agora eu quero instalar e usar no meu servidor virtual na hosteurope. A instalação básica não foi problema, mas agora tenho problemas com meu projeto de compilação.

Depois de puxar uma atualização mercurial de um repositório, ant é invocado e lança o seguinte erro no meu projeto de construção:

"Buildfile: /var/lib/jenkins/workspace/concrete5-seed-clean/build.xml  [property] java.io.IOException: Não é possível executar o programa "/ usr / bin / env": java.io.IOException: error = 12, Não é possível alocar memória "

Existe um problema conhecido com o tamanho do heap em servidores virtuais no hosteurope ( link ), então eu tentou definir o tamanho de heap manualmente:

# for ant
export ANT_OPTS="-Xms512m -Xmx512m"

# jenkins
# edited /etc/default/jenkins, added line 
JAVA_ARGS="-Xms512m -Xmx512m"
# restarted jenkins via /etc/init.d/jenkins restart 

Depois de definir isso como formiga, o comando "ant -diagnostics" é executado e não causa um erro, mas o erro ainda ocorre quando tento construir o projeto.

Detalhes do servidor: - link

  • Ubuntu 10.4 LTS
  • RAM: 1 GB / 2 GB dinâmicos

Minhas perguntas: - É 1GB suficiente para Jenkins ou eu tenho que atualizar o servidor? - Esse erro é causado por formigas ou jenkins?

Atualização: Eu consegui executar com ant opções -Xmx128m -Xms128m, mas às vezes o erro ocorre novamente. (isso me assusta, porque eu não posso reproduzi-lo agora: /)

Ajuda muito apreciada!

Felicidades, Matias

    
por Programmieraffe 29.09.2011 / 22:03

3 respostas

9

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 para fork() 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 use posix_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

    
por 04.03.2012 / 06:31
0

É provável que ANT_OPTS seja substituído por Jenkins. Você também pode definir as opções diretamente no seu arquivo de compilação para que possa controlar a alocação de memória independentemente do ambiente (shell, Jenkins, ...). No seu arquivo de compilação (exemplo:

<java fork="true" classname="..." >
    <jvmarg line="-Xms512M -Xmx512M" />
    
por 30.09.2011 / 07:11
0

Observe a mensagem de exceção: Cannot run program "/usr/bin/env": java.io.IOException: error=12, Cannot allocate memory" O processo Java está tentando bifurcar um novo processo para executar o comando /usr/bin/env , mas o sistema operacional ficou sem recursos de memória para criar um novo processo. Isso não é o mesmo que a VM Java que está ficando sem memória, de modo que nenhuma quantidade de mexer com sinalizadores -Xmx consertará isso. Você precisará monitorar seus recursos de memória enquanto executa sua compilação. Aumentar o espaço de troca provavelmente resolverá seu problema.

    
por 04.11.2011 / 21:45

Tags