-
Bug
-
Resolution: Incomplete
-
P4
-
None
-
10.0.2
-
x86_64
-
windows_10
ADDITIONAL SYSTEM INFORMATION :
Windows 10, Version 10.0.16299 Build 16299.
IDE: Oxygen.3a Release (4.7.3a)
Compiler: JDT for JavaSE-9
VM info:
java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)
Can be reproduced with Java 9.
A DESCRIPTION OF THE PROBLEM :
When
# an enum type E with a non-default constructor is defined inside a class A, and
# this class A defines a static final constant C, and
# an enum value of E uses this constant C for construction, and
# the class A uses the enum E somewhere in a switch statement (no matter where - even in non-reachable code),
then accessing the enum E (e.g. one of its values) from another class causes a ExceptionInInitializerError due to a NullPointerException in the values() method of the enum.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See source code for details.
(1) write a class A.
(2) define a constant C inside this class.
(3) define a enum E inside this class with a one-argument-constructor. The constructor can be empty.
(4) define an enum value V inside E that uses the constant C for construction.
(5) add an arbitrary method to the class that uses the enum in a switch statement.
(6) write another class with a main method and simply access the enum values there (e.g. call A.E.values() );
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
VM terminates normally
ACTUAL -
VM terminates with the following error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at MyClass$State.<clinit>(SwitchBug.java:12)
at SwitchBug.main(SwitchBug.java:4)
Caused by: java.lang.NullPointerException
at MyClass$State.values(SwitchBug.java:1)
at MyClass.$SWITCH_TABLE$MyClass$State(SwitchBug.java:8)
at MyClass.<clinit>(SwitchBug.java:9)
... 2 more
---------- BEGIN SOURCE ----------
// --- file SwitchBug.java ---
public class SwitchBug {
public static void main(String[] args) {
// access enum values from an other class
MyClass.State.values();
}
}
class MyClass {
private static final Object C = "";
public enum State {
ENABLED(C); // pass null constant
State(Object value) {} // value can be ignored
}
/* unused method with switch statement IN SAME CLASS */
private static void unusedMethod() {
switch (State.ENABLED) {
case ENABLED:
break;
}
}
}
// --- end of file ---
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Some modifications of the code above can solve the issue:
# don't use a switch statement in MyClass. (remove the "unusedMethod()").
# don't use the constant C for enum construction (e.g. use the literal "" directly instead of C).
# change the type of the constant C from Object to String.
# create an instance of MyClass before accessing the enum (i.e. new MyClass(); before calling MyClass.State.values()).
FREQUENCY : always
Windows 10, Version 10.0.16299 Build 16299.
IDE: Oxygen.3a Release (4.7.3a)
Compiler: JDT for JavaSE-9
VM info:
java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)
Can be reproduced with Java 9.
A DESCRIPTION OF THE PROBLEM :
When
# an enum type E with a non-default constructor is defined inside a class A, and
# this class A defines a static final constant C, and
# an enum value of E uses this constant C for construction, and
# the class A uses the enum E somewhere in a switch statement (no matter where - even in non-reachable code),
then accessing the enum E (e.g. one of its values) from another class causes a ExceptionInInitializerError due to a NullPointerException in the values() method of the enum.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See source code for details.
(1) write a class A.
(2) define a constant C inside this class.
(3) define a enum E inside this class with a one-argument-constructor. The constructor can be empty.
(4) define an enum value V inside E that uses the constant C for construction.
(5) add an arbitrary method to the class that uses the enum in a switch statement.
(6) write another class with a main method and simply access the enum values there (e.g. call A.E.values() );
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
VM terminates normally
ACTUAL -
VM terminates with the following error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at MyClass$State.<clinit>(SwitchBug.java:12)
at SwitchBug.main(SwitchBug.java:4)
Caused by: java.lang.NullPointerException
at MyClass$State.values(SwitchBug.java:1)
at MyClass.$SWITCH_TABLE$MyClass$State(SwitchBug.java:8)
at MyClass.<clinit>(SwitchBug.java:9)
... 2 more
---------- BEGIN SOURCE ----------
// --- file SwitchBug.java ---
public class SwitchBug {
public static void main(String[] args) {
// access enum values from an other class
MyClass.State.values();
}
}
class MyClass {
private static final Object C = "";
public enum State {
ENABLED(C); // pass null constant
State(Object value) {} // value can be ignored
}
/* unused method with switch statement IN SAME CLASS */
private static void unusedMethod() {
switch (State.ENABLED) {
case ENABLED:
break;
}
}
}
// --- end of file ---
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Some modifications of the code above can solve the issue:
# don't use a switch statement in MyClass. (remove the "unusedMethod()").
# don't use the constant C for enum construction (e.g. use the literal "" directly instead of C).
# change the type of the constant C from Object to String.
# create an instance of MyClass before accessing the enum (i.e. new MyClass(); before calling MyClass.State.values()).
FREQUENCY : always