Enum.valueOf bug with JDK 7 SE where .values() gets corrupted

enums, java, java-7

Solution

Actually we found the issue. It's a face + palm moment. We corrupted the enum via reflection API's by attempting a deep (nonshallow) copy of a class containing an enum. This had the effect of wiping out all instance variables of the singleton enum itself. Thanks for all the assistance and suggestions.

Problem

This seems like a crazy error, but `Enum.valueOf(type, name)` seems to be unstable on Oracle JDK 7 SE. The manifestation is that, on the exact same name String (I've verified this), the call to `valueOf()` sometimes throws `IllegalArgumentException` with the message `No enum constant ...`. My team ran this through the Eclipse debugger, and what we noticed is that in the following JDK implementation of valueOf on enum, `enumConstantDirectory()`, i.e. the `values()` list for an enum, sometimes seem to be missing some values. Not the entirety of all the values defined in the enum itself. I can work around the bug by calling `Enum.valueOf(enumclass.class, "XXX")` for all possible enum values on JVM startup. When I do this, it seems `values()` always contains the full set. However, if I don't do this type of initialization, sometimes `Enum.valueOf()` will throw an `IllegalArgumentException`. Context: I'm seeing this problem when using XStream 1.4.4 to convert POJO objects that convert enum, but the problem doesn't seem to be inherently with XStream. Has anyone seen this kind of error? I would love to hear about it if you have. It boggles my mind. Is this a bug in the Oracle JDK/JVM implementation? ``` public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { T result = enumType.enumConstantDirectory().get(name); if (result != null) return result; if (name == null) throw new NullPointerException("Name is null"); throw new IllegalArgumentException( "No enum constant " + enumType.getCanonicalName() + "." + name); } ``` Other relevant details: We are using the `org.reflections` library to scan all enums in our code at startup. During the scanning, we take the type of the enum, and call `clazz.getEnumConstants()` on the Class object associated with the enum. This might be a relevant detail. In looking and the `java.lang.Class.getEnumConstants()` implementation, it seems to share the same `enumConstants` shared object within the Class. I wonder if there's a problem with the implementation here. Our enum is pretty simple, no static initialization, etc. ``` public enum ScreeningRuleType { INSERT, CONFIRMATION, AMOUNT, EXISTENCE, BAN, SELECTION, CUSTOM; private long id; private String descr; ScreeningRuleType() { id = this.ordinal(); descr= this.toString().replace("_", " "); } } ``` Edit: In experimenting with this, I'm finding another manifestation. After using the System.out initialization, now instead of throwing IllegalArgumentException, the value returned by Enum.valueOf seems to be random. This shows what I'm seeing in the Eclipse debugger. It clearly shows I'm calling valueOf() on the string "EXISTENCE" and "EXISTENCE".intern(), and clearly shows it's returning AMOUNT() instead.

Original source

Related problems