Pergunta

Esta é a minha primeira pergunta em S. O.
Eu tenho um muito estranho problema.
Abaixo está o meu problema...

Eu escrevo método muito simples que escrever um texto para um arquivo.
É claro que ele funciona bem, a minha máquina(XP, 4CPU, jdk1.5.0_17[SOL])
Mas somtimes congela em um servidor operacionais
(Linux Accounting240 2.4.20-8smp, 4CPU, jdk1.5.0_22[SOL]).

matar -3 não funciona.
ctrl + \ não funciona.

Então, eu não posso mostrar a você o segmento de despejo.

Ele congela bem..Quando eu acabei de escrever alguma Thread.sono(XX) neste método, o problema é ido bem(?)...
sono(XX) quebrar...aconteceu hoje, mais uma vez, com Rosca.sono(XX)...

Você conhece esse problema?Você tem alguma solução sobre o que?Obrigado.:-)

P. S.
distribuição linux:Red Hat Linux 3.2.2-5
comando:java -cp .T

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class T {
private BufferedWriter writer = null;

private void log(String log) {
    try {
        if (writer == null) {
            File logFile = new File("test.log");
            writer = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(logFile, true)));
        }
        writer.write(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss] ")
                .format(new Date()));
        writer.write("[" + log + "]" + "\n");
        writer.flush();

         /*
                         *  this is ad hoc solution ???
                         */
        //Thread.sleep(10);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {         
    }

}

public void test() {
    long startTime = System.currentTimeMillis();

    while (true) {
        log(String.valueOf(System.currentTimeMillis()));
        System.out.println(System.currentTimeMillis());
        try {
            //Thread.sleep((int) (Math.random() * 100));
        } catch (Exception e) {
            break;
        }

        if (System.currentTimeMillis() - startTime > 1000 * 5) {
            break;
        }
    }

    if (writer != null) {
        try {
            writer.close();
        } catch (Exception e) {
        }
    }
    System.out.println("OK");
}

public static void main(String[] args) {
    new T().test();
}
}
Foi útil?

Solução

Se a JVM não responde a matar -3, então ele não é o seu programa, mas a JVM que está a falhar, o que é ruim e exigiria um relatório de bug para o Sol.

Eu percebi que você está executando um 2.4.20-8smp kernel.Este não é um típico kernel para uma corrente de fonte aberta distribuição de Linux, então eu sugiro que você dê uma olhada no http://java.sun.com/j2se/1.5.0/system-configurations.html para ver se você está implantando uma configuração suportada.Se não, você deve deixar o responsável gente sabe isso!

Outras dicas

O primeiro passo é obter um despejo de thread de onde está o programa quando "congela". Se isso estivesse no Java 6, você poderia conectar o JVisualVM ou o JCONSOLE por padrão e obter as trilhas de empilhamento de todos os threads a partir daí. Como é Java 5, você deve poder usar o jstack Comando para obter um despejo de thread (ou você pode ativar o JMX com uma opção de linha de comando para anexar as ferramentas acima mencionadas, mas não acho que valha a pena neste caso). Em todos os casos, pressionar Ctrl-Break no console que lançou o aplicativo também pode produzir um despejo de encadeamento, dependendo do ambiente.

Faça isso várias vezes com alguns segundos de distância e compare os despejos de threads. Se eles sempre são idênticos, parece que seu aplicativo está impulsionado; E a linha superior do dump mostrará exatamente onde os threads estão bloqueando (o que dará uma pista muito boa, quando você olhar para essa linha do código, quais recursos estão bloqueados).

Por outro lado, se os dumps de threads mudarem de tempos em tempos, o programa não será estritamente implementado, mas parece que está funcionando em um loop infinito - talvez uma das condições do seu loop não seja declarada corretamente para que os threads nunca saiam ou algo desse tipo . Novamente, observe o conjunto de despejos de threads para ver qual área de código cada encadeamento está entrando, o que lhe dará uma idéia da condição de loop que nunca está avaliando para uma condição de saída.

Se o problema não for óbvio nesta análise, poste os despejos, pois ajudará as pessoas a depurar seu código acima.

Eu acho que isso é uma condição de corrida. o while(true) forçará a VM no Linux a escrever e lavar continuamente, e a VM do kernel Linux tentará interceptar essas chamadas e buffer a escrita. Isso fará com que o processo spinloop enquanto aguardará a conclusão do syscall; Ao mesmo tempo, será apanhado pelo agendador e atribuído a outra CPU (posso estar errado aqui, Tho). A nova CPU tentará adquirir um bloqueio no recurso e tudo resultará em um impasse.

Isso pode ser um sinal de outras questões por vir. Eu sugiro:

  • Primeiro de tudo, por causa da clareza: mova a criação de arquivos fora do log() método. É para isso que servem os construtores.

  • Em segundo lugar, por que você está tentando escrever para um arquivo como esse? Tem certeza de que sua lógica do programa faz sentido em primeiro lugar? Você não prefere escrever suas mensagens de log em um contêiner (digamos, uma lista de Array) e a cada xx segundos despejando isso no disco em um encadeamento separado? No momento, você está limitando sua capacidade de registro à velocidade do seu disco: algo que você pode querer evitar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top