verificar Forzar Java para llamar a mi destructor de C++(JNI)




¿cómo activar el plugin de java en google chrome? (4)

Después de mirar un poco más el código producido por SWIG, veo que las personas SWIG ya se han ocupado de esto, agregan una función delete () para usted. Parece bastante bien cuidado de la posibilidad de que tanto el programador como el GC eliminen el objeto también.

Pensé que esta pregunta se habría hecho antes, pero no pude encontrarla aquí ...

He usado SWIG para crear un contenedor JNI en torno a una clase C ++. Todo funciona bien, excepto que Java nunca parece llamar al finalize () de la clase, por lo que, a su vez, nunca se llama al destructor de mi clase. El destructor de la clase hace algo de E / S de archivo final, así que desafortunadamente, esto no es solo una fuga de memoria menor.

Buscando a través de Google, no parece haber una forma de forzar a Java a GC y destruir un objeto. ¿Cierto?

Sé que podría manipular mi archivo SWIG y crear una función java que llamaría al destructor C ++, pero esta clase es utilizada por los usuarios finales en varias plataformas / idiomas diferentes, por lo que la adición de un solo Java creará una inconsistencia que nuestra tecnología a los escritores no les va a gustar.


Si confía en el código en el método de finalize para ejecutarse en un momento determinado, debe reconsiderar su enfoque. El problema aquí es que no sabes cuándo se llamará a finalize por JVM, ya que no sabes cuándo se recogerá el objeto.

Una cosa que debe considerar, ya que su clase será reutilizada en otros proyectos, es que es posible que un usuario final pueda usar una instancia de una clase de tal manera que no se recopile o que la recolección de basura no es probable, como crear una referencia estática a una instancia de la clase. Creo que la creación de un método de close o destroy es la apuesta más segura para garantizar que los recursos que utiliza la instancia de la clase C ++ asociada a su objeto Java se liberen de forma adecuada.

Dado que la reutilización es una preocupación, puede hacer que el destructor de C ++ verifique si los recursos se han liberado y que se llame al mismo código si no lo hubieran sido, así:

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();
  }
}

De esta forma, su código C ++ existente no tendrá que cambiar mucho, y puede asegurarse de que sus recursos se liberen de manera determinista en el contexto del código nativo que se ejecuta a través de JNI.


Cuestiones como esta son la razón por la que C # eligió el patrón IDisposable para la finalización determinista.

Sugiero que siga el mismo patrón y lo adapte para sus usuarios de Java.

En su clase de c ++, cree un método público separado que disponga de sus recursos. Llámalo cerca, o deséchalo, o algo así.

Haga que su destructor de C ++ llame al método público y diga a los usuarios de GC / gestión de la clase C ++ que deben llamar al método para evitar pérdidas de memoria.


No puede forzar GC con System.gc (). Además, no está garantizado que alguna vez se ejecute un GC, por ejemplo, si su aplicación se ejecuta solo por un tiempo corto y luego su finalizador no se ejecutará en absoluto (la JVM no lo ejecutará al salir). Debes crear un close () o destroy () o cualquier función para tu clase y cuando termines de usar una instancia de esta clase llámala, preferiblemente de un bloque finally, como.


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




jni