Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 提供相同哈希代码的两个不同类实例_Java_Ognl - Fatal编程技术网

Java 提供相同哈希代码的两个不同类实例

Java 提供相同哈希代码的两个不同类实例,java,ognl,Java,Ognl,我在JBoss服务器上遇到了一个奇怪的问题,其中两个类产生相同的hashCode() 我通常不会在意,但我们使用的框架使用一个键缓存setter,该键由类中的哈希代码和属性名组成。这是一个糟糕的缓存设计,但目前我无法控制(最新的Struts 2.3.24版本中的OGNL 3.0.6,请参阅。较新的OGNL解决了这个问题,但它将在Struts中出现,直到2.5版本,目前处于测试阶段。) 让我觉得这个问题有点奇怪的是 使用几天后出现问题。。。我很确定在这段时间内,两个类/属性都被缓存了。这让我相信

我在JBoss服务器上遇到了一个奇怪的问题,其中两个类产生相同的
hashCode()

我通常不会在意,但我们使用的框架使用一个键缓存setter,该键由类中的哈希代码和属性名组成。这是一个糟糕的缓存设计,但目前我无法控制(最新的Struts 2.3.24版本中的OGNL 3.0.6,请参阅。较新的OGNL解决了这个问题,但它将在Struts中出现,直到2.5版本,目前处于测试阶段。)

让我觉得这个问题有点奇怪的是

  • 使用几天后出现问题。。。我很确定在这段时间内,两个类/属性都被缓存了。这让我相信类实例哈希代码实际上正在改变。。。几天后他们变得平等了
  • 我们在一个非常过时的热点1.6中观察到了这种行为,现在在1.7.0_80上。两者都是基于Sun Sparc的32位构建
  • JVM报告-XX:哈希代码为“0”
我读到Hotspot中的RNG hashcode生成器(“0”策略)可以在有争用线程的情况下生成副本,但我无法想象类加载会触发这种行为

Hotspot在创建
实例时是否使用特殊的hashcode处理

  • java.lang.Class
    不会覆盖
    hashCode
    ,JVM也不会以某种方式专门处理它。这只是从
    java.lang.Object
    继承的常规标识哈希代码
  • -XX:hashCode=0
    (JDK 6和JDK 7中的默认值)时,使用global Park Miller随机数生成器计算标识hashCode。该算法生成周期为
    2^31-2
    的唯一整数,因此两个对象几乎不可能具有相同的hashCode,原因如下
  • 由于该算法依赖于一个不同步的全局变量,因此确实存在两个不同线程由于竞争条件生成相同随机数的可能性。你的情况显然就是这样
  • 标识hashCode不是在对象创建时生成的,而是在第一次调用
    hashCode
    方法时生成的。因此,何时以及如何加载类并不重要。如果同时调用
    hashCode
    ,则任何两个对象都可能发生此问题
  • 我建议使用
    -XX:hashCode=5
    (JDK 8中的默认值)。此选项使用线程本地Xorshift RNG。它不受竞赛条件的限制,并且比Park-Miller算法更快

  • 我认为它们不会随着时间的推移而改变。那太奇怪了。你能确认它们在一开始就不一样吗?@Thilo我不能100%地确定哈希代码并不总是一样的。我所知道的是,在试图设置框架操作属性时,我提到的缓存机制在这种情况下肯定会失败。从历史上看,这正是我们观察到的问题。我刚刚重新部署了,哈希代码是不同的。我只需要等待几天/几周,直到问题返回,然后再次运行类测试。这两个类是什么子类?它们可能有一个覆盖
    hashCode()
    @FSQ的父级,因为它们不是特定类的实例。它们是
    java.lang.Class
    的实例,它是
    final
    ,并以本机方式生成哈希代码。标识哈希代码是一个非常小的数字,对我来说似乎很奇怪。哇,一个很好的解释!我非常怀疑类加载器是否以多线程方式初始化这些类。。。但你的解释使这一点无关紧要。很可能这些类的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