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.