Pergunta

Eu pensei que esta questão teria sido solicitado antes, mas eu não poderia encontrá-lo aqui ...

Eu usei SWIG para criar um wrapper JNI em torno de uma classe C ++. Todos os trabalhos grandes, exceto que Java nunca parece chamar finalize da classe (), então, por sua vez, destruidor da minha classe nunca é chamado. destructor da classe faz algum arquivo final I / O, então, infelizmente, isso não é apenas uma fuga de memória menor.

Como pesquisar através do Google, não parece ser uma maneira de forçar Java para GC e destruir um objeto. Verdade?

Eu sei que eu poderia manipular meu arquivo SWIG e criar uma função java que iria chamar o destruidor C ++, mas esta classe é usada pelos usuários finais em vários diferentes plataformas / linguagens, então a adição de um Java-só irá criar uma inconsistência que nossos escritores de tecnologia não vão gostar.

Foi útil?

Solução

Você não pode forçar GC com System.gc (). Também não é garantido que nunca haverá uma corrida GC por exemplo, se o seu aplicativo é executado apenas por um curto período de tempo e, em seguida, o seu finalizador não será executado em todos (a JVM não executá-lo quando sair). Você deve criar um close () ou destruir () ou qualquer função para a sua classe e quando você terminar de usar uma instância dessa chamada classe-lo, de preferência a partir de um bloco finally, como.


MyClass x = null;
try{
    x = new MyClass();
    x.work();
} finally {
    if (x!=null)
        x.close();
}

Outras dicas

finalizadores

Java são praticamente inúteis, na minha opinião, e certamente não um substituto para destruidores C ++. Infelizmente, Java não tem substituto para C ++ RAII.

Não se preocupe em tentar forçar a finalização Java. Quando você está completamente com o que quer, tudo uma função que irá descartá-lo. Isso é tudo o que você pode fazer.

Se você está confiando em código no método finalize para executar em um determinado momento, você precisa reconsiderar sua abordagem. O problema aqui é que você não sabe quando finalize será chamado pela JVM, desde que você não sabe quando o objeto será coletado.

Uma coisa que você deve considerar, desde a sua classe será em outros projetos reutilizado, é que é possível que um usuário final pode usar uma instância de uma classe de tal forma a que não serão recolhidos ou que recolha de lixo será improvável, tais como a criação de uma referência estática para uma instância da classe. Eu acho que a criação de um close ou método destroy é a sua aposta mais segura de garantir que os recursos da instância da classe do C ++ associado com o objeto Java está usando são liberados de forma adequada.

Uma vez que a reutilização é uma preocupação, você poderia ter o cheque destrutor C ++ para ver se os recursos foram liberados e chamar o mesmo código, se não tivessem sido, assim:

class MyThing {
  public:
    void close();
    ~MyThing();

  private:
    bool released = false;
};

void
MyThing::close() {
  // close logic here
  this->released = true;
}

MyThing::~MyThing() {
  if (!released) {
    this->close();
  }
}

Desta forma, seu código existente C ++ espero que não terá que mudar muito, e você pode garantir que seus recursos são liberados de forma determinística no contexto de código nativo rodando via JNI.

Depois de um pouco mais olhando através do código de SWIG-produzido, vejo que as pessoas SWIG realmente já lidaram com isso - eles adicionar uma função delete () para você. Parece que muito bem cuidado a possibilidade de tanto o programador e o GC excluir o objeto também.

Questões como esta são a razão C # escolheu o IDisposable padrão para a finalização determinística.

Eu sugiro que você siga o mesmo padrão e adaptá-lo para seus usuários Java.

Na sua classe c ++, criar um método separado, público que dispõe de seus recursos. Chamá-lo de perto, nem descarte, ou algo assim.

Tenha o seu destruidor C ++ chamar o método público, e informar aos usuários gerenciados / GC da classe C ++ que eles devem chamar o método para evitar vazamentos de memória.

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