web-dev-qa-db-fra.com

En Java, comment vérifier que AutoCloseABeABeABeABe a été appelé?

Je crée un =Java Library. Certaines des classes destinées à être utilisées par les utilisateurs de la bibliothèque, organisent des ressources système natales (sur JNI). J'aimerais assurer que l'utilisateur "dispose "Ces objets, comme ils sont lourds et dans un test, ils peuvent causer des fuites entre testicules (par exemple, je dois m'assurer que TearDown va disposer). À cette fin, j'ai fait le Java Les classes implémentent autoclotionable, mais cela ne semble pas suffire, ni je ne l'utilise pas correctement:

  1. Je ne vois pas comment utiliser try-with-resources Instruction dans le contexte des tests (j'utilise JUnit5 Avec Mockito), en ce que la "ressource" n'est pas courte. vécu - cela fait partie du dispositif de test.

  2. Être diligent comme toujours, j'ai essayé de mettre en œuvre finalize() _ et testez la fermeture là-bas, mais il s'avère finalize() n'est pas appelé (Java10). Ceci est également marqué comme obsolète et je suis sûr que cette idée sera fronçée.

Comment est-ce fait? Pour être clair, je souhaite que les tests de l'application (qui utilisent ma bibliothèque) pour échouer s'ils n'appellent pas close() sur mes objets.


Edit: Ajout du code si cela aide. Ce n'est pas beaucoup, mais c'est ce que j'essaie de faire.

@SuppressWarnings("deprecation") // finalize() provided just to assert closure (deprecated starting Java 9)
@Override
protected final void finalize() throws Throwable {
    if (nativeHandle_ != 0) {
         // TODO finalizer is never called, how to assert that close() gets called?
        throw new AssertionError("close() was not called; native object leaking");
    }
}

Edit2, Résultat de Bounty Merci à tous de répondre, la moitié de la prime a été automatiquement attribuée. J'ai conclu que pour mon cas, il serait préférable d'essayer la solution impliquant Cleaner. Cependant, il semble que les actions de nettoyage bien enregistrées ne soient pas invoquées. J'ai demandé une question de suivi ici .

29
haelix

je fournirais des occurrences à ces objets à travers Factory methods et avec cela, j'ai le contrôle de la création d'eux, et je vais nourrir les consommateurs avec Proxies qui fait la logique de fermeture l'objet

interface Service<T> {
 T execute();
 void close();
}

class HeavyObject implements Service<SomeObject> {
  SomeObject execute() {
  // .. some logic here
  }
  private HeavyObject() {}

  public static HeavyObject create() {
   return new HeavyObjectProxy(new HeavyObject());
  }

  public void close() {
   // .. the closing logic here
  }
}

class HeavyObjectProxy extends HeavyObject {

  public SomeObject execute() {
    SomeObject value = super.execute();
    super.close();
    return value;
  }
}
0
mehdi maick