Frage

Ich dachte, diese Frage vor gefragt worden wäre, aber ich konnte es nicht finden Sie hier ...

Ich habe SWIG verwendet, um einen JNI-Wrapper um eine C ++ Klasse zu erstellen. Alle funktioniert gut, außer dass Java scheint nie die Klasse des finalize () zu nennen, so, wiederum destructor meine Klasse wird nie genannt. Die destructor Klasse hat einige letzte Datei-I / O, so leider ist dies nicht nur ein kleiner Speicherverlust.

Die Suche in Google, es scheint nicht ein Weg, um Java zu zwingen, um ein Objekt zu GC und zu zerstören. Stimmt das?

Ich weiß, ich könnte meine SWIG-Datei manipulieren und eine Java-Funktion erstellen, die den C ++ destructor nennen würden, aber diese Klasse von Endanwendern in mehreren verschiedenen Plattformen / Sprachen verwendet wird, so dass die Zugabe von einer Java-only wird eine Inkonsistenz erstellen dass unsere Tech-Autoren wollen nicht wie.

War es hilfreich?

Lösung

Sie können nicht zwingen, GC mit System.gc (). Auch ist es nicht garantiert, dass es jemals ein GC läuft zum Beispiel, wenn die App nur für eine kurze Zeit laufen und dann Finalizerthread wird nicht ausgeführt (die JVM nicht, es laufen beim Beenden). Sie sollten ein close () oder zerstören () oder was auch immer Funktion für Ihre Klasse erstellen und wenn Sie fertig eine Instanz dieser Klasse nennen, vorzugsweise aus einem finally-Block, wie.


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

Andere Tipps

Java Finalizers meist nutzlos, meiner Meinung nach, und schon gar nicht ein Ersatz für C ++ Destruktoren. Leider Java hat keinen Ersatz für C ++ RAII.

Sie sich nicht die Mühe versucht, Java Finalisierung zu erzwingen. Wenn Sie fertig sind mit dem, was auch immer, alle einer Funktion, die darüber verfügen wird. Das ist alles, was Sie tun können.

Wenn Sie auf Code in der finalize Methode unter Berufung zu einem bestimmten Zeitpunkt ausgeführt werden, müssen Sie Ihren Ansatz zu überdenken. Das Problem hierbei ist, dass Sie nicht wissen, wann finalize wird von der JVM aufgerufen werden, da Sie nicht wissen, wenn das Objekt wird Müll gesammelt werden.

Eine Sache, die man beachten sollte, da Ihre Klasse in anderen Projekten wiederverwendet werden, ist, dass es möglich ist, dass ein Endbenutzer eine Instanz einer Klasse in einer solchen Art und Weise nutzen könnten, dass sie nicht oder gesammelt werden, dass Garbage-collection wird unwahrscheinlich, wie beispielsweise eine statische Referenz auf eine Instanz der Klasse zu schaffen. Ich denke, die Schaffung eines close oder destroy Methode ist die sicherste Wette, um sicherzustellen, dass die Ressourcen, die Instanz der C ++ Klasse, die mit Java-Objekt verwenden, werden in geeigneter Weise veröffentlicht.

Da wiederverwenden ein Anliegen ist, können Sie den C ++ destructor überprüfen, um zu sehen, ob die Ressourcen freigegeben worden war und den gleichen Code zu nennen, wenn sie nicht gewesen wäre, etwa so:

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

Auf diese Weise Ihre vorhandenen C ++ Code hoffentlich wird nicht viel ändern müssen, und Sie können sicherstellen, dass Ihre Ressourcen in einer deterministischen Art und Weise im Rahmen freigegeben werden von nativen Code über JNI ausgeführt wird.

Nach weiteren Blick durch die SWIG-erzeugte Code, sehe ich, dass die SWIG Leute haben tatsächlich schon mit diesem behandelt - sie für Sie eine delete () Funktion hinzuzufügen. Es scheint ziemlich gut betreut die Möglichkeit sowohl der Programmierer und der GC als auch das Objekt zu löschen.

Fragen wie diese sind der Grund, C # wählte die IDisposable Muster für deterministische Finalisierung.

Ich schlage vor, Sie folgen dem gleichen Muster und es für Ihre Java-Benutzer anzupassen.

In C ++ Klasse, erstellen Sie eine separate, öffentliche Methode, die Ihre Ressourcen verfügen. Nennen Sie es schließen oder entsorgen, oder so etwas.

Haben Sie Ihre C ++ destructor die öffentliche Methode nennen, und sagen Managed / GC Benutzer der C ++ Klasse, dass sie die Methode aufrufen müssen Speicherlecks zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top