Porque meu programa Java com vazamento de memória quando eu chamo run () em um objeto Thread?

votos
27

(Pergunta Jeopardy de estilo, eu desejo a resposta tinha sido on-line quando eu tive esse problema)

Usando Java 1.4, eu tenho um método que eu quero correr como um fio por algum tempo, mas não em outros. Então eu declarou-o como uma subclasse de Thread, então, ou chamado start () ou run () dependendo do que eu precisava.

Mas eu descobri que o meu programa iria vazar memória ao longo do tempo. O que estou fazendo de errado?

Publicado 20/09/2008 em 11:19
fonte usuário
Em outras línguas...                            


3 respostas

votos
45

Este é um bug conhecido em Java 1.4: http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=5869e03fee226ffffffffc40d4fa881a86e3:WuuT?bug_id=4533087

É fixa em Java 1.5, mas Sun não pretende corrigi-lo em 1,4.

A questão é que, no momento da construção, um Threadé adicionado a uma lista de referências em uma tabela rosca interna. Não será removido dessa lista até que seu método start () foi concluída. Enquanto que a referência está lá, não vai ficar lixo coletado.

Assim, nunca criar um thread a menos que você está indo definitivamente para chamar seu start()método. Um Threadobjeto run()método não deve ser chamado diretamente.

A melhor maneira de codificar é para implementar a Runnableinterface de, em vez de subclasse Thread. Quando você não precisa de um fio, chamada

myRunnable.run();

Quando você precisa de um fio:

Thread myThread = new Thread(myRunnable);
myThread.start();
Respondeu 20/09/2008 em 11:25
fonte usuário

votos
3

Eu duvido que a construção de uma instância de um tópico ou uma subclasse do mesmo vazamentos de memória. Em primeiro lugar, não há nada dos tipos mencionados no Javadocs ou a especificação da linguagem Java. Em segundo lugar, eu corri um teste simples e também mostra que nenhuma memória é perdida (pelo menos não no da Sun JDK 1.5.0_05 em 32-bit x86 Linux 2.6):

public final class Test {
  public static final void main(String[] params) throws Exception {
    final Runtime rt = Runtime.getRuntime();
    long i = 0;
    while(true) {
      new MyThread().run();
      i++;
      if ((i % 100) == 0) {
        System.out.println((i / 100) + ": " + (rt.freeMemory() / 1024 / 1024) + " " + (rt.totalMemory() / 1024 / 1024));
      }
    }
  }

  static class MyThread extends Thread {
    private final byte[] tmp = new byte[10 * 1024 * 1024];

    public void run() {
      System.out.print(".");
    }
  }
}

EDIT: Só para resumir a idéia do teste acima. Cada instância da subclasse MyThread de uma linha referente ao seu próprio conjunto de 10 MB. Se as instâncias de MyThread não eram coleta de lixo, a JVM iria ficar sem memória muito rapidamente. No entanto, a execução do código de teste mostra que a JVM é usando uma pequena quantidade constante de memória, independentemente do número de MyThreads construídos até agora. Eu reivindico isso é porque os casos de MyThread são coleta de lixo.

Respondeu 20/09/2008 em 12:26
fonte usuário

votos
2

Vamos ver se podemos chegar mais perto ao núcleo do problema:

Se você começar o seu programa (digamos) 1000 x usando start (), de 1000 x usando run () em um segmento, fazer as duas coisas memória solta? Se assim for, então o seu algoritmo deve ser verificado (ou seja, para objetos externos tais como vetores usados ​​em seu Runnable).

Se não existe tal vazamento de memória como descrito acima, então você deve investigar sobre os parâmetros iniciais e uso de memória de tópicos sobre a JVM.

Respondeu 20/09/2008 em 11:26
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more