Вопрос

According to jls § 8.9.2 Enum Body Declarations

It is a compile-time error for an enum declaration to declare a finalizer. An instance of an enum type may never be finalized.

As finalizer executes just before Garbage Collector runs, if finalizer is not present does that means enum type always remains loaded in memory, and Garbage Collector is not applicable on enum type?

Это было полезно?

Решение

If you compile an enum like

enum Suit {SPADES, HEARTS, CLUBS, DIAMONDS}

You will see that the generated bytcodes (i.e. javap -p Suit) correspond to a synthetic class:

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

So, instances of the enum are static members of the class itself. Then I think the only way in which this could be garbage collected would be if the class itself is garbage collected, which is very unlikely to happen if it was loaded by the system class loader.

Другие советы

Does Garbage Collector run on Enum type?

Just an experiment to show that the enum instances can be made gc eligible.

Define a sample enum as follows -

public enum SampleEnum { ONE; }

And the test code -

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!");

Try it with the -verbose:gc option.


As finalizer executes just before Garbage Collector runs, if finalizer is not present does that means enum type always remains loaded in memory, and Garbage Collector is not applicable on enum type?

Actually the presence/absence of finalizer does not have anything to do with whether or not any object will be gc'ed. The enum instances are not gc'ed because they are referred to by the static fields within the enum class generated by the compiler.

I believe that since enum's and enum types are always static it would behave as if it were a static member since it could be accessed at any time.

Additionally finalizers are designed to be invoked when an Object is unloaded from memory as they are intended to perform any necessary cleanup operation and you can't make objects of Enum's.

It's a curious couple of sentences.

It is a compile-time error for an enum declaration to declare a finalizer.

That's clear enough. I don't know why that would be the case, but the rules are the rules. This also appears to be enforced by the fact that enums derive from Enum, and the API spec says that Enum has a final finalizer.

An instance of an enum type may never be finalized.

The language here seems ambiguous to me. Are they declaring that no instance of an enum type will ever be finalized? If so, why "may"? Why not just say so? Are they just reminding us that finalization isn't guaranteed to occur? Either way, it doesn't matter....

Object's finalize method is defined to do nothing (12.6). Enum derives from Object, and enums derive from Enum. Enum's finalizer isn't defined to do anything, and you can't override it, so when you put it all together the finalization of an enum instance has no effects.

In my interpretation, the enum instances can be garbage collected (although as others have pointed out the circumstances that allow this to happen are a bit unusual), and as their finalize method is defined not to do anything, whether or not the finalize method is ever called is a moot point.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top