Pergunta

Nós temos uma aplicação bastante grande e complexo escrito em Java que é executado no topo do pacote Gridgain. O problema que estou tendo é que esta aplicação vai sentar-se lá o processamento de pedidos por aproximadamente um dia antes de cada pedido começa resultando em uma exceção do tipo java.nio.channels.ClosedByInterruptException.

A minha suposição é que o aplicativo não está liberando identificadores de arquivo e depois de um dia de uso contínuo que se esgote e já não pode continuar a processar pedidos (cada pedido requer a leitura de vários arquivos de cada nó da rede). Temos envolveu a maioria das nossas operações de arquivo IO nas aulas, como um presente

package com.vlc.edge;

import com.vlc.common.VlcRuntimeException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public final class BufferedReaderImpl implements BufferedReader {
    private java.io.BufferedReader reader;

    public BufferedReaderImpl(final String source) {
        this(new File(source));
    }

    public BufferedReaderImpl(final File source) {
        try {
            reader = new java.io.BufferedReader(new FileReader(source));
        } catch (FileNotFoundException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public BufferedReaderImpl(final Reader reader) {
        this.reader = new java.io.BufferedReader(reader);
    }

    public String readLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public void close() {
        try {
            reader.close();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }
}

Eu acho que o problema é que este projeto não libera explicitamente o identificador de arquivo, a minha solução proposta é adicionar um método finalize como este

    protected void finalize() throws Throwable
    {
        reader.close();
        super.finalize();   
    }

que irá fazer isso explicitamente. A pergunta (finalmente) é se este é ou não provável que tenha qualquer efeito. Fazer classes como java.io.BufferedReader já tem algum mecanismo para lidar com este tipo de problema?

EDIT:? Também muito apreciada aqui seria formas de verificar se este é realmente o problema ... ou seja, há uma maneira para consultar uma JVM em execução e perguntar sobre isso de alocações de identificador de arquivo

Foi útil?

Solução

Há pouco ponto em substituir finalize(). Se a alça está sendo coletado e finalizado, então que é a instância de java.io.BufferedReader e ele vai ficar fechado.

É possível (de acordo com a especificação) que a alça está sendo lixo coletado, mas não finalizado, mas isso não é muito provável.

Você pode tentar usar PhantomReferences para limpar identificadores de arquivos não utilizados, mas meu palpite é que suas instâncias do BufferedReaderImpl ainda são referenciados de algum lugar (por exemplo, valores em um Map de nomes para identificadores abertos) e que é o que está impedindo-os de serem fechada (em que finalizadores caso não vai ajudar.)

Outras dicas

Finalizadores não pode ser invocado para ser chamado. Não é uma boa abordagem para a gestão de recursos. A construção padrão em Java para isso é:

InputStream in = null;
try {
  in = ...;
  // do stuff
} catch (IOException e) {
  // error
} finally {
  if (in != null) { try { in.close(); } catch (Exception e) { } }
  in = null;
}

Você pode querer embrulhar estas alças dentro de uma classe, mas isso não é uma abordagem robusta.

especificação Java diz que não é garantia de que 'finalize()' será executado. Seu código deve explicitamente perto FileReader si mesmo.

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