java – 提供相同hashCode的两个不同的Class实例

前端之家收集整理的这篇文章主要介绍了java – 提供相同hashCode的两个不同的Class实例前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在JBoss服务器上遇到一个奇怪的问题,其中两个类生成相同的hashCode().
Class<?> cl1 = Class.forName("fqn.Class1");
Class<?> cl2 = Class.forName("fqn.Class2");
out.println(cl1.getCanonicalName());
out.println(cl2.getCanonicalName());
out.println(cl1.hashCode());
out.println(cl2.hashCode());
out.println(System.identityHashCode(cl1));
out.println(System.identityHashCode(cl2));
out.println(cl1 == cl2);
out.println(cl1.equals(cl2));
out.println(cl1.getClassLoader().equals(cl2.getClassLoader()));

生产:

fnq.Class1
fnq.Class2
494722
494722
494722
494722
false
false
true

我通常不会在意,但是我们正在使用一个框架,它使用由类和属性名称的哈希码构成的密钥来缓存设置器.这是缓存的一个坏设计,但目前无法控制(OGNL 3.0.6在最新的Struts 2.3.24,请参阅source.一个较新的OGNL修复了这个问题,但直到2.5,Struts将不会在目前在beta.)

这个问题让我有些奇怪

>问题出现在使用几天后,我很确定在这段时间内,类/属性都被缓存.这使我相信类实例哈希码实际上正在改变…他们在几天后变得平等.
>我们已经观察到一个非常过时的Hotspot 1.6的行为,现在在1.7.0_80.两者都是Sun Sparc上的32位构建
> JVM报告-XX:hashCode为“0”

我读到,HotSpot中的RNG哈希码生成器(“0”策略)可以产生重复的,如果有赛车线程,但我无法想象类加载触发该行为.

在创建Class实例时,Hotspot是否使用特殊的哈希码处理?

解决方法

> java.lang.Class不会覆盖hashCode,JVM也不会特别处理它.这只是从java.lang.Object继承的常规身份hashCode.
>当-XX:hashCode = 0(在JDK 6和JDK 7中为默认值)时,使用全局Park-Miller随机生成器计算身份hashCode.该算法产生的周期为2 ^ 31-2的唯一整数,所以几乎没有机会两个对象具有相同的hashCode,除了以下原因.
>由于该算法依赖于不同步的全局变量,因此,由于竞争条件 (the source),两个不同的线程确实有可能产生相同的随机数.这在您的情况下显然会发生. >在创建对象时不会生成Identity hashCode,而是在首次调用hashCode方法生成.所以加载类的时间和方式无关紧要.如果同时调用了hashCode,任何两个对象都可能会发生此问题. >我建议使用-XX:hashCode = 5(JDK 8中的默认值).此选项使用线程本地Xorshift RNG.它不受竞争条件的影响,也比Park-Miller算法更快.

猜你在找的Java相关文章