Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Life span of a Java enum instance

Tags:

java

enums

I understand there is one single instance per predefined constant of an enum type. Is that even right? Now, suppose there is an instance variable called value of the enum, and suppose ONE is a predefined constant. If value is modified for (the) instance of ONE then this affects all variables referring to ONE. But what happens to the value of value when the garbage collector gets rid of all instances of the enum? Do they ever get thrown away even?

Example

Here is a simple example where there are two variables A and B, both referring to ONE. The value of value is negated before B is used for the first time. If the garbage collector had gotten rid of the instance of ONE before the line Number B = Number.ONE;, then the value of value would have been "reset" back to 1, I presume. Is this correct?

The enum:

public enum Number
{
    ONE(1), TWO(2), THREE(3); 

    int value;

    Number(int value) { this.value = value; }

    void negate() { value = -value; }

    @Override
    public String toString() { return "value: " + value; }
}

The main method:

public static void main(String[] args)
{
    Number A = Number.ONE;
    A.negate();
    Number B = Number.ONE;

    System.out.println(A + "   " + B);
}

Output:

value: -1 value: -1

So my question is, can the output ever be the following (if say A = null; is added before B is used)?

value: -1 value: 1

like image 240
DustByte Avatar asked Jul 11 '15 11:07

DustByte


2 Answers

Enums are implicitly public static final fields, so they are never garbage collected.

EDIT

As kindly pointed out in the comments by @RealSkeptic, things are a little bit more complex in a jvm instance with multiple class loaders. Then static field values may disapear when their classes are unloaded.

However, by default, there is only one class loader which is alive as long as the jvm instance is alive, so in your example application it can never happen that static fields are garbage collected.

like image 96
Dragan Bozanovic Avatar answered Sep 29 '22 06:09

Dragan Bozanovic


For this enum:

public enum FooEnum {
  CONST
}

This byte code is generated:

Compiled from "FooEnum.java"
public final class FooEnum extends java.lang.Enum<FooEnum> {
  public static final FooEnum CONST;

  static {};
    Code:
       0: new           #1                  // class FooEnum
       3: dup
       4: ldc           #12                 // String CONST
       6: iconst_0
       7: invokespecial #13                 // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #17                 // Field CONST:LFooEnum;
      13: iconst_1
      14: anewarray     #1                  // class FooEnum
      17: dup
      18: iconst_0
      19: getstatic     #17                 // Field CONST:LFooEnum;
      22: aastore
      23: putstatic     #19                 // Field ENUM$VALUES:[LFooEnum;
      26: return

  public static FooEnum[] values();
    // elided

  public static FooEnum valueOf(java.lang.String);
    // elided
}

CONST is a final static variable whose lifetime is that of the class.

Enums will only be garbage collected if the class is garbage collected.

From The Java Language Specification, Java SE 8 Edition section 8.9. Enum Types:

An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type (§15.9.1).

In addition to the compile-time error, three further mechanisms ensure that no instances of an enum type exist beyond those defined by its enum constants:

The final clone method in Enum ensures that enum constants can never be cloned.

Reflective instantiation of enum types is prohibited.

Special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.

like image 24
McDowell Avatar answered Sep 29 '22 08:09

McDowell