简体   繁体   English

EnumMap具有来自不同类加载器的键的奇怪行为

[英]Strange behavior of EnumMap with keys from different classloaders

I encountered strange behavior of enum type loaded by different class loader. 我遇到了由不同的类加载器加载的enum类型的奇怪行为。 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. 我使用调试器检查GLOBAL_SYSTEM_MAP是否正确,包含适当的值,但get()方法仍然未返回任何正确的值。

I suspect that the reason may be connected with different class loaders used by both applications to load MyEnumType type. 我怀疑原因可能与两个应用程序用来加载MyEnumType类型的不同类加载器有关。 But on the other hand, the enum's equals() method is probably prepared for such a case, isn't it? 但是,另一方面,枚举的equals()方法可能是为这种情况准备的,不是吗? So, maybe the EnumMap.get() implementation uses == instead of equals()? 因此,也许EnumMap.get()实现使用==而不是equals()? (but I rather doubt that) I also tried replace EnumMap by HashMap but this didn't solve the problem either. (但我很怀疑)我也尝试用HashMap替换EnumMap,但这也不能解决问题。

EnumMap checks the actual class of the key you pass in against the class of the enum it was created with. EnumMap对照传入的枚举类检查传入的键的实际类。 If they are different, get will return null. 如果它们不同,则get将返回null。 The class will be different since you are loading the MyEnum class twice with different classloaders. 该类将有所不同,因为您使用不同的类加载器两次加载了MyEnum类。

The fix is to arrange for both applications use a shared instance of the MyEnum class. 解决方法是安排两个应用程序使用MyEnum类的共享实例。

enum values loaded by different class loader should neither be == or equals . 由不同类加载器加载的enum值不应为==equals You should generally get some kind of error if treating different classes with the same name from different class loaders as the same. 如果将来自不同类加载器的具有相同名称的不同类视为相同,通常应该会遇到某种错误。 Is the type of GLOBAL_SYSTEM_MAP Map<MyEnumType,String> or Map<?,String> (or similar)? GLOBAL_SYSTEM_MAP的类型是Map<MyEnumType,String>还是Map<?,String> (或类似名称)?

One possible reason for an error to be hidden is that some class loaders do not delegate to their parent first (IIRC, breaks the Java SE spec, recommended by the EE specs). 隐藏错误的一个可能原因是某些类加载器没有首先委派给其父级(IIRC违反了EE规范建议的Java SE规范)。 This causes all manner of problems. 这会引起各种问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM