Domanda

Pensavo che questa domanda sarebbe stata posta prima, ma non sono riuscito a trovarla qui ...

Ho usato SWIG per creare un wrapper JNI attorno a una classe C ++. Tutto funziona alla grande, tranne che Java non sembra mai chiamare finalize () della classe, quindi, a sua volta, il distruttore della mia classe non viene mai chiamato. Il distruttore della classe esegue alcuni I / O del file finale, quindi sfortunatamente non si tratta solo di una piccola perdita di memoria.

Cercando su Google, non sembra esserci un modo per forzare Java a GC e distruggere un oggetto. Vero?

So che potrei manipolare il mio file SWIG e creare una funzione java che chiamerebbe il distruttore C ++, ma questa classe viene utilizzata dagli utenti finali in diverse piattaforme / lingue, quindi l'aggiunta di un solo Java creerà un'incoerenza che non piaceranno ai nostri scrittori di tecnologia.

È stato utile?

Soluzione

Non puoi forzare GC con System.gc (). Inoltre non è garantito che ci sarà mai una corsa GC, ad esempio se la tua app viene eseguita solo per un breve periodo e quindi il tuo finalizzatore non funzionerà affatto (la JVM non la esegue quando si esce). Dovresti creare una funzione close () o destroy () o qualunque altra per la tua classe e quando hai finito di usare un'istanza di questa classe chiamala, preferibilmente da un blocco finally, come.


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

Altri suggerimenti

I finalizzatori Java sono per lo più inutili, secondo me, e certamente non sostituiscono i distruttori C ++. Sfortunatamente, Java non ha un sostituto per C ++ RAII.

Non preoccuparti di forzare la finalizzazione Java. Quando hai finito con qualunque cosa, tutta una funzione che la eliminerà. Questo è tutto ciò che puoi fare.

Se fai affidamento sul codice nel metodo finalize per essere eseguito in un determinato momento, devi riconsiderare il tuo approccio. Il problema qui è che non sai quando finalize verrà chiamato da JVM, poiché non sai quando l'oggetto verrà raccolto.

Una cosa che dovresti considerare, poiché la tua classe verrà riutilizzata in altri progetti, è che è possibile che un utente finale possa utilizzare un'istanza di una classe in modo tale che non venga raccolta o che la garbage collection sarà improbabile, come la creazione di un riferimento statico a un'istanza della classe. Penso che la creazione di un metodo close o destro sia la scommessa più sicura per garantire che le risorse utilizzate dall'istanza della classe C ++ associata all'oggetto Java vengano rilasciate in modo appropriato.

Poiché il riutilizzo è un problema, è possibile che il distruttore C ++ verifichi se le risorse sono state rilasciate e di chiamare lo stesso codice se non lo fossero, in questo modo:

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

In questo modo, si spera che il tuo codice C ++ esistente non cambi molto, e puoi assicurarti che le tue risorse vengano rilasciate in modo deterministico nel contesto del codice nativo in esecuzione tramite JNI.

Dopo aver esaminato meglio il codice prodotto da SWIG, vedo che le persone SWIG hanno già risolto questo problema, aggiungendo una funzione delete () per te. Sembra essere abbastanza ben curato della possibilità che sia il programmatore che il GC cancellino anche l'oggetto.

Problemi come questo sono il motivo per cui C # ha scelto IDisposable modello per la finalizzazione deterministica.

Ti suggerisco di seguire lo stesso modello e adattarlo per i tuoi utenti Java.

Nella tua classe c ++, crea un metodo pubblico separato che elimini le tue risorse. Chiamalo vicino, o getta, o qualcosa del genere.

Chiedi al distruttore C ++ di chiamare il metodo pubblico e di indicare agli utenti gestiti / GC della classe C ++ che devono chiamare il metodo per evitare perdite di memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top