2009-06-18 12 views
9

ho pensato a questa domanda sarebbe stato chiesto prima, ma non ho potuto trovare qui ...forza Java per chiamare il mio distruttore C++ (JNI)

ho usato SWIG per creare un wrapper JNI intorno ad un Classe C++. Tutto funziona alla grande eccetto 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 di file finali, quindi sfortunatamente non si tratta solo di una piccola perdita di memoria.

Ricerca in Google, non sembra essere 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 è utilizzata dagli utenti finali in diverse piattaforme/lingue, quindi l'aggiunta di un solo Java creerà un incoerenza che i nostri scrittori tecnologici non gradiranno.

risposta

7

Non è possibile forzare GC con System.gc(). Inoltre, non è garantito che esista un GC, ad esempio se l'app viene eseguita solo per un breve periodo di tempo e quindi il tuo finalizzatore non verrà eseguito affatto (la JVM non lo esegue all'uscita). Dovresti creare una funzione close() o destroy() o qualsiasi altra funzione 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(); 
} 
5

I finalizzatori Java sono per lo più inutili, a mio parere, e certamente non sostituiscono i distruttori C++. Sfortunatamente, Java non ha sostituto per C++ RAII.

Non preoccupatevi di provare a forzare la finalizzazione di Java. Quando hai finito con quello che vuoi, tutte le funzioni che lo elimineranno. Questo è tutto ciò che puoi fare.

0

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

Suggerisco di seguire lo stesso schema e adattarlo per gli utenti Java.

Nella classe C++, creare un metodo pubblico separato che disponga delle risorse. Chiamalo vicino, o disponi o qualcosa.

Il distruttore C++ chiama il metodo pubblico e comunica agli utenti GC/gestiti della classe C++ che devono chiamare il metodo per evitare perdite di memoria.

5

Se si sta facendo affidamento sul codice nel metodo finalize da eseguire in un determinato momento, è necessario riconsiderare l'approccio. Il problema qui è che non si sa quando finalize verrà chiamato dalla JVM, poiché non si sa quando l'oggetto sarà spazzato via.

Una cosa che dovresti considerare, dato che la tua classe sarà riutilizzata in altri progetti, è che è possibile che un utente finale possa usare un'istanza di una classe in modo tale da non essere raccolta o la raccolta di dati inutili è improbabile, ad esempio la creazione di un riferimento statico a un'istanza della classe. Penso che la creazione di un metodo close o destroy sia la tua scommessa più sicura per garantire che le risorse utilizzate dall'istanza della classe C++ associata all'oggetto Java vengano rilasciate in modo appropriato.

Dal riutilizzo è un problema, si potrebbe avere il controllo di C++ distruttore per vedere se le risorse fossero stati liberati e di chiamare lo stesso codice, se non fossero stati, 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, il tuo codice C++ esistente non dovrebbe cambiare molto, e puoi assicurarti che le tue risorse vengano rilasciate in modo deterministico nel contesto del codice nativo eseguito tramite JNI.

3

Dopo aver esaminato il codice prodotto da SWIG, vedo che in realtà le persone SWIG lo hanno già risolto: aggiungono una funzione delete(). Sembra piuttosto ben curato la possibilità che sia il programmatore che il GC cancellino l'oggetto.

Problemi correlati