加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 16:17:19 所属栏目:Java 来源:网络整理
导读:我在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.h
我在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算法更快.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读