Search code examples
javaenumsclassloader

Strange behavior of EnumMap with keys from different classloaders


I encountered strange behavior of enum type loaded by different class loader. In common library I have enum definition (similar to the following):

enum MyEnumType { VAL_1, VAL_2, VAL_3 };

I have first application which creates following map and registers it as some kind of global in the system (the registration code is only symbolic for simplicity):

final Map<MyEnumType, String> map = new EnumMap<MyEnumType, String>(MyEnumType.class);
map.put(MyEnumType.VAL_1, "value 1");
map.put(MyEnumType.VAL_2, "value 2");
map.put(MyEnumType.VAL_3, "value 3");
GLOBAL_SYSTEM_MAP = Collections.unmodifiableMap(map);

The second application (with different class loader) performs following operation:

String value = GLOBAL_SYSTEM_MAP.get(MyEnumType.VAL_1);

and receives null value. I checked using debugger that the GLOBAL_SYSTEM_MAP was correct, contained appropriate values, yet get() method still didn't return any correct value.

I suspect that the reason may be connected with different class loaders used by both applications to load MyEnumType type. But on the other hand, the enum's equals() method is probably prepared for such a case, isn't it? So, maybe the EnumMap.get() implementation uses == instead of equals()? (but I rather doubt that) I also tried replace EnumMap by HashMap but this didn't solve the problem either.


Solution

  • EnumMap checks the actual class of the key you pass in against the class of the enum it was created with. If they are different, get will return null. The class will be different since you are loading the MyEnum class twice with different classloaders.

    The fix is to arrange for both applications use a shared instance of the MyEnum class.