33 votes

Le Garbage Collector fonctionne-t-il sur le type Enum ?

Selon jls § 8.9.2 Déclarations de corps d'Enum

C'est une erreur de compilation pour une déclaration d'enum de déclarer un finalisateur. Une instance d'un type enum ne peut jamais être finalisée.

Comme le finaliseur s'exécute juste avant le Garbage Collector, si le finaliseur n'est pas présent, cela signifie que enum reste toujours chargé en mémoire, et Garbage Collector n'est pas applicable sur enum type ?

39voto

Edwin Dalorzo Points 19899

Si vous compilez un enum comme

enum Suit {SPADES, HEARTS, CLUBS, DIAMONDS}

Vous verrez que les bytcodes générés (c.-à-d. javap -p Suit ) correspondent à une classe synthétique :

final class Suit extends java.lang.Enum<Suit> {
  public static final Suit SPADES;
  public static final Suit HEARTS;
  public static final Suit CLUBS;
  public static final Suit DIAMONDS;
  private static final Suit[] $VALUES;
  public static Suit[] values();
  public static Suit valueOf(java.lang.String);
  private Suit();
}

Ainsi, les instances de l'enum sont des membres statiques de la classe elle-même. Alors je pense que la seule façon dont cela pourrait être ramassé serait si la classe elle-même est ramassée, ce qui est très peu probable si elle a été chargée par le chargeur de classe du système.

14voto

Bhesh Gurung Points 24875

Le Garbage Collector fonctionne-t-il sur le type Enum ?

C'est juste une expérience pour montrer que les instances de l'enum peuvent être rendues éligibles pour le gc.

Définissez un exemple d'enum comme suit -

public enum SampleEnum { ONE; }

Et le code de test -

Class<SampleEnum> clazz = SampleEnum.class;
String[] fieldNames = {
    "ONE", "ENUM$VALUES"
};
//create a weak reference to the instance
WeakReference<SampleEnum> ref = new WeakReference<SampleEnum>(SampleEnum.ONE);
//remove the hard references
for (String fieldName: fieldNames) {
    Field feld = clazz.getDeclaredField(fieldName);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(feld, feld.getModifiers() & ~Modifier.FINAL);
    feld.setAccessible(true);
    feld.set(null, null);
}
//wait until a gc occurs and clears the weak ref
while (ref.get() != null) {
    System.out.println("Waiting ...");
    System.gc();
}
//output just to verify that the weak ref is cleared by the gc
System.out.println("Weak reference is cleared!");

Essayez-le avec le -verbose:gc option.


Comme le finaliseur s'exécute juste avant le Garbage Collector, si le finaliseur n'est pas présent, cela signifie-t-il que le type enum reste toujours chargé en mémoire et que le Garbage Collector ne s'applique pas au type enum ?

En fait, la présence ou l'absence d'un finalisateur n'a rien à voir avec le fait qu'un objet soit ou non gc'ed. Les instances de l'enum ne sont pas gc'ed parce qu'elles sont référencées par les champs statiques de la classe de l'enum générée par le compilateur.

4voto

tommycake50 Points 90

Je pense qu'étant donné que les enum et les types d'enum sont toujours statiques, il se comporterait comme s'il s'agissait d'un membre statique puisqu'on pourrait y accéder à tout moment.

En outre, les finaliseurs sont conçus pour être invoqués lorsqu'un objet est déchargé de la mémoire, car ils sont destinés à effectuer toute opération de nettoyage nécessaire et vous ne pouvez pas créer des objets d'Enum.

4voto

Samuel Edwin Ward Points 3192

C'est un curieux couple de phrases.

C'est une erreur de compilation pour une déclaration d'enum de déclarer un finalisateur.

C'est assez clair. Je ne sais pas pourquoi ce serait le cas, mais les règles sont les règles. Cela semble également être appliqué par le fait que les enums dérivent de Enum et les spécifications de l'API indiquent que Enum a un final finaliseur.

Une instance d'un type enum ne peut jamais être finalisée.

Le langage utilisé ici me semble ambigu. Est-ce qu'ils déclarent qu'aucune instance d'un type enum ne sera jamais finalisée ? Si oui, pourquoi "peut" ? Pourquoi ne pas simplement le dire ? Est-ce qu'ils nous rappellent simplement que la finalisation n'est pas garantie ? Quoi qu'il en soit, cela n'a pas d'importance.....

Object 's finalize est définie pour ne rien faire ( 12.6 ). Enum provient de Object et les enums dérivent de Enum . Enum Le finalisateur de l'utilisateur n'est pas défini pour faire quoi que ce soit, et vous ne pouvez pas le surcharger, donc quand vous mettez tout ensemble la finalisation d'une instance d'enum n'a aucun effet.

Selon mon interprétation, les instances d'enum peuvent être récupérées (bien que, comme d'autres l'ont souligné, les circonstances qui permettent cela soient un peu inhabituelles), et comme leur finalize est définie pour ne rien faire, que la méthode finalize est jamais appelée est un point discutable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X