Question

Je pensais que cette question aurait déjà été posée, mais je ne pouvais pas la trouver ici ...

J'ai utilisé SWIG pour créer un wrapper JNI autour d'une classe C ++. Tout fonctionne très bien, sauf que Java ne semble jamais appeler finalize () de la classe. Ainsi, le destructeur de ma classe n'est jamais appelé. Le destructeur de la classe effectue des E / S de fichier finales, donc malheureusement, il ne s’agit pas d’une fuite de mémoire mineure.

En recherchant sur Google, il ne semble pas y avoir de moyen de forcer Java à GC et à détruire un objet. Vrai?

Je sais que je pourrais manipuler mon fichier SWIG et créer une fonction java qui appellerait le destructeur C ++, mais cette classe est utilisée par les utilisateurs finaux sur plusieurs plates-formes / langages différentes. Par conséquent, l'ajout d'une interface Java uniquement créera une incohérence. que nos rédacteurs techniques ne vont pas aimer.

Était-ce utile?

La solution

Vous ne pouvez pas forcer GC avec System.gc (). En outre, il n’est pas garanti qu’il y ait un jour une exécution de GC, par exemple, si votre application ne fonctionne que pendant une courte période, puis votre finaliseur ne fonctionnera pas du tout (la JVM ne l’exécute pas lors de la fermeture). Vous devez créer une fonction close () ou destroy () ou une fonction quelconque pour votre classe. Lorsque vous avez fini d'utiliser une instance de cette classe, appelez-la, de préférence depuis un bloc finally, comme.


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

Autres conseils

Les finaliseurs Java sont pour la plupart inutiles, à mon avis, et certainement pas pour remplacer les destructeurs C ++. Malheureusement, Java n’a pas de remplacement pour C ++ RAII.

Ne cherchez pas à forcer la finalisation Java. Quand vous en avez fini avec tout, une fonction qui en disposera. C'est tout ce que vous pouvez faire.

Si vous utilisez le code de la méthode finalize pour s'exécuter à un moment donné, vous devez reconsidérer votre approche. Le problème ici est que vous ne savez pas quand finalize sera appelé par la JVM, car vous ne savez pas quand l'objet sera nettoyé.

Une chose à considérer, puisque votre classe sera réutilisée dans d'autres projets, est qu'il est possible qu'un utilisateur final utilise une instance d'une classe de telle sorte qu'elle ne soit pas collectée ou que Une récupération de place sera peu probable, telle que la création d'une référence statique à une instance de la classe. Je pense que la création d'une méthode close ou destroy est votre meilleur pari pour vous assurer que les ressources utilisées par l'instance de la classe C ++ associée à votre objet Java sont libérées de manière appropriée.

La réutilisation étant un problème, vous pouvez demander au destructeur C ++ de vérifier si les ressources ont été libérées et d'appeler le même code si elles ne l'avaient pas été, comme suit:

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 cette façon, votre code C ++ existant n'aura probablement plus à changer, et vous pouvez vous assurer que vos ressources sont libérées de manière déterministe dans le contexte du code natif exécuté via JNI.

Après un peu plus de recherche dans le code produit par SWIG, je constate que les responsables de SWIG ont déjà traité ce problème - ils ajoutent une fonction delete () pour vous. Il semble que la possibilité que le programmeur et le GC suppriment l’objet soit également prise en compte.

C’est la raison pour laquelle C # a choisi IDisposable modèle pour la finalisation déterministe.

Je vous suggère de suivre le même schéma et de l'adapter à vos utilisateurs Java.

Dans votre classe c ++, créez une méthode publique séparée qui dispose de vos ressources. Appelez ça près, ou jetez ou quelque chose comme ça.

Demandez à votre destructeur C ++ d'appeler la méthode publique et dites aux utilisateurs gérés / GC de la classe C ++ qu'ils doivent appeler la méthode pour éviter les fuites de mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top