Tomcat no servidor virtual: a JVM não pode ser iniciada porque o Ram de 44 GB não é suficiente?

1

Estou alugando uma máquina virtual, executando o Ubuntu 9.04. Eu instalei o SUN JDK 6.0 (via apt-get) e o Tomcat 6.0.18 (via descompactação).

Problema geral com Java (parcialmente resolvido)

Inicialmente, era impossível executar uma JVM por causa de problemas de memória. Mesmo algo simples como java -version falhou com

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Eu descobri que mesmo que free relatasse 44 GB de memória livre, eu só podia usar uma pequena fração dele, algo como 284 MB por alocação. A execução de java -Xms10m -Xmx256m -version funciona bem, mas não quero alterar todos os scripts que chamam java.

Também li sobre a variável de ambiente JAVA_OPTS , que é considerada por muitos aplicativos. Eu configurei isso para "-Xms10m -Xmx256m"

Problema com o Tomcat

O script de inicialização do tomcat catalina.sh também usa JAVA_OPTS . Mas evento ainda, eu ainda recebo as três linhas de erro mencionadas acima, legível em logs/catalina.out . Eu sei que JAVA_OPTS é usado, porque quando eu coloco um absurdo nessa variável, vejo as conseqüências em logs/catalina.out .

Parece que o Tomcat também deseja iniciar o javac, que precisa das opções prefixadas com -J like -J-Xms10m -J-Xmx256m . Mas não tenho certeza se isso está relacionado ao problema, porque não há mais saída do que essas três linhas.

Estou começando o Tomcat por meio de bin/startup.sh , que por sua vez chama bin/catalina.sh . Eu sei que há também a possibilidade de iniciá-lo via jsrv , mas não posso fazer isso, porque o processo de make / configure para jsrv também deseja chamar javac , que falha com a conhecida mensagem de erro de três linhas mencionada acima .

Agora, eu estaria interessado em dois possíveis tipos de solução:

  • como posso fazer o Java funcionar apenas em meu host virtual, não importa quem chama java ou javac e não importa como ele o chama?
  • se isso for impossível, como posso ajustar o Tomcat para apenas executar?

PS: Por favor, note que eu só tenho controle sobre a máquina virtual, mas nenhum controle e apenas conhecimento limitado sobre / sobre a máquina física circundante.

PPS: Desculpem o título noobish desta pergunta, mas eu senti que o título original e bem escrito não atraiu leitores suficientes, então eu pensei que isso poderia ajudar;) Isso realmente ajudou, já que recebi 0 visualizações na primeira hora, mas 8 visualizações na hora após a alteração. Mundo estranho.

Edit: esta é a saída de ulimit -a :

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
    
por Lena Schimmel 19.12.2009 / 16:21

5 respostas

1

javac geralmente gera um processo separado que deve cair sob regras de processo diferentes.

-J opções são para passar args através de um wrapper / launcher para a JVM, eu não vi isso no Tomcat.

Descubra de onde vem o -Xmx:

find /your/install/dir/with/tomcat |xargs grep '-Xmx'

    
por 19.12.2009 / 23:06
0

Tente executar ulimit -v unlimited antes de iniciar o tomcat. Se isso funcionar, você provavelmente poderá adicioná-lo a um ou ambos os scripts de inicialização ou a /etc/profile , ~/.bashrc ou outro script de perfil de shell.

    
por 20.12.2009 / 02:42
0

Na falta de alternativas eu tentei um hack sujo: substituindo java e javac por scripts de shell que garantem que os argumentos apropriados sejam passados e permitam-me ver a lista de parâmetros exata. Como isso já é uma tentativa de uma solução muito específica, e não parte da pergunta, eu gostaria de colocá-la em uma resposta.

Eu procurei todas as ocorrências de java no meu sistema de arquivos. Havia muitas maneiras, porque eu tenho vários JREs e JDKs na minha máquina. Mesmo depois de remover todas as versões, exceto uma, ainda havia muitas delas. Eu usei find / -name "java" |xargs file para descobrir qual é o real . Ele me disse:

/var/lib/dpkg/alternatives/java:               ASCII text
/etc/alternatives/java:                        symbolic link to '/usr/lib/jvm/java-6-sun/jre/bin/java'
/usr/share/java:                               directory
/usr/lib/jvm/java-6-sun-1.6.0.16/bin/java:     symbolic link to '../jre/bin/java'
/usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/java: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.4.0, not stripped
/usr/bin/java:                                 symbolic link to '/etc/alternatives/java'

Então eu sabia que /usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/java era o executável. Eu o renomei para javaexec e coloquei um script de shell no local antigo:

mv /usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/java /usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/javaexec
nano /usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/java
   (see below for file contents)
chmod +x #!/bin/bash -e

Isso garante que todas as chamadas para java nos pontos finais do meu script chame o executável com os parâmetros corretos. Depois disso, fiz coisas terríveis semelhantes com javac . O conteúdo do meu script:

#!/bin/bash -e
line=""
for i in $*
do
  if [[ "$i" == *Xmx* ]]; then
    echo "Seen -Xmx and removed"
  elif [[ "$i" == *MaxPerm* ]]; then
    echo "Seen -XX:MaxPermSize and removed"
  else
    line="$line $i"
  fi
done
exec="/usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/javaexec -Xms10m -Xmx100m $line"
echo Now executing $exec
$exec

Ele remove cada um dos parâmetros da linha de comando que envolve -Xmx ou algo parecido com -XX:MaxPermSize e coloca seus próprios limites -Xms e -Xmx.

Quando inicio o Tomcat, ele ainda falha, mas, finalmente, a JVM inicia, faz algo e sai com uma mensagem significativa. Não tenho sucesso, mas me deixa muito mais satisfeita, já que a partir daí sei o que fazer. Enquanto o Tomcat ainda não funciona, ele tem um bom efeito colateral:

Agora posso finalmente chamar java ou javac na linha de comando ou de um script, e eles não travam, o que antes não era possível em tudo ! Eles apenas executam ! Ei, eu me sinto como o rei da palavra, finalmente consegui que o java rodasse em uma máquina com 44GB de Ram sem reclamar sobre memória insuficiente. Este é um ótimo dia na história da computação, de fato!

    
por 20.12.2009 / 14:13
0

Você também pode verificar o java vms que você instalou. Certifique-se de que não é o ambiente do gcj que está causando problemas.

tente

update-java-alternatives -l

para ver se sun-java6 é seu padrão. Solte "-l" para ver as outras opções para este comando - por exemplo, como mudar o padrão.

Se bem me lembro, todos os problemas de java que eu tive no Ubuntu tiveram suas raízes no gcj sendo o padrão (ele pode ter entrado como alguma dependência antes do sun-java6). Se não me lembro bem, é pelo menos a maioria dos problemas.

Por último, mas não menos importante (e relacionado apenas à sua pergunta): Você pode colocar um arquivo chamado "setenv.sh" no diretório bin do tomcat. Este arquivo não está lá, mas será lido na inicialização se puder ser encontrado. Você pode fazer todas as alterações aqui para se referir a elas mais tarde. A única desvantagem é que eles serão lidos na inicialização e no desligamento.

    
por 20.12.2009 / 19:22
0

Uma vez eu tive problema semelhante. Você pode tentar iniciar o java com

vm.overcommit_memory=1

definido em /etc/sysctl.conf. Ou simplesmente echo "1" > /proc/sys/vm/overcommit_memory

Ou brinque com overcommit_memory, overcommit_ratio link

    
por 03.02.2011 / 19:00