java.lang.Object.equals 和 java.lang.Object.hashCode 在序列化后处理 jruby 对象时遇到问题
我在使用 jruby 对象到 java
java side
package com.pp;
public interface ZeroI {
boolean equals(Object o);
int hashCode();
int hash();
}
package com.pp;
public class Tester {
public Object[] compare(ZeroI one, ZeroI two) {
return new Object[] {one.hashCode(), two.hashCode(), one.equals(two), one == two};
}
}
jruby side
include Java
import com.pp.Tester
import com.pp.ZeroI
module MMM
module Zero
def hash= value
@hash = value
end
def hash
@hash
end
def hashCode
@hash
end
def equals other
false
end
def == other
true
end
end
class OneClass
include ZeroI
include Zero
end
class TwoClass
include ZeroI
include Zero
end
def self.create clazz
begin
dump = IO.readlines("C:/#{clazz.to_s.rpartition('::')[2]}.txt", '').to_s
instance = Marshal.load dump
rescue => err
puts err.message
instance = clazz.new
dump = Marshal.dump instance
File.open("C:/#{clazz.to_s.rpartition('::')[2]}.txt", 'w') { |f| f.write dump }
end
instance
end
tester = Tester.new
one = create OneClass
two = create TwoClass
puts one
puts two
one.hash = 22
two.hash = 22
puts one.hashCode
puts two.hashCode
puts one.equals two
puts one == two
tester.compare(one, two).each { |value| puts value }
end
First pass result:
No such file or directory - C:/OneClass.txt
No such file or directory - C:/TwoClass.txt
#<MMM::OneClass:0x1971eb3>
#<MMM::TwoClass:0x1408a75>
22
22
false
true
22
22
true
false
true # 没关系,因为 JAVA.equals 与 JRUBY.==
false # 没关系,因为 org.pp.ZeroI 无法声明 == 方法和 JAVA .== 使用
第二遍结果(带有反序列化对象)
#<MMM::OneClass:0xd510e8>
#<MMM::TwoClass:0x490342>
22
22
false
true
13046738 # but what is it?
31877484 # but what is it?
false # but what is it?
false
有人能解释一下吗?
I have some trouble using jruby objects into java
java side
package com.pp;
public interface ZeroI {
boolean equals(Object o);
int hashCode();
int hash();
}
package com.pp;
public class Tester {
public Object[] compare(ZeroI one, ZeroI two) {
return new Object[] {one.hashCode(), two.hashCode(), one.equals(two), one == two};
}
}
jruby side
include Java
import com.pp.Tester
import com.pp.ZeroI
module MMM
module Zero
def hash= value
@hash = value
end
def hash
@hash
end
def hashCode
@hash
end
def equals other
false
end
def == other
true
end
end
class OneClass
include ZeroI
include Zero
end
class TwoClass
include ZeroI
include Zero
end
def self.create clazz
begin
dump = IO.readlines("C:/#{clazz.to_s.rpartition('::')[2]}.txt", '').to_s
instance = Marshal.load dump
rescue => err
puts err.message
instance = clazz.new
dump = Marshal.dump instance
File.open("C:/#{clazz.to_s.rpartition('::')[2]}.txt", 'w') { |f| f.write dump }
end
instance
end
tester = Tester.new
one = create OneClass
two = create TwoClass
puts one
puts two
one.hash = 22
two.hash = 22
puts one.hashCode
puts two.hashCode
puts one.equals two
puts one == two
tester.compare(one, two).each { |value| puts value }
end
First pass result:
No such file or directory - C:/OneClass.txt
No such file or directory - C:/TwoClass.txt
#<MMM::OneClass:0x1971eb3>
#<MMM::TwoClass:0x1408a75>
22
22
false
true
22
22
true
false
true # it's OK because JAVA.equals works with JRUBY.==
false # it's OK because org.pp.ZeroI can't declare == method and JAVA.== is used
Second pass result (with deserialized objects)
#<MMM::OneClass:0xd510e8>
#<MMM::TwoClass:0x490342>
22
22
false
true
13046738 # but what is it?
31877484 # but what is it?
false # but what is it?
false
Can anybody explain it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道为什么会发生这种情况的所有细节,但我为您提供了一个解决方案/解决方法。 (当将 ruby 端创建的对象传递到 Java 端时,我看到了类似的行为。)
据我所知,JRuby 需要已经“看到”它正在尝试解组的类的实例,然后才能进行解组。正确处理 Java 继承方面的问题。就好像在 JRuby 中创建一个对象有一个未记录的副作用,它会注册所需的继承层次结构。如果说得不好,那是因为我自己也不明白!
因此,解决方法是在进行解组之前简单地创建
OneClass
和TwoClass
的实例。如果我将self.create
方法更改为以下内容:那么两遍的输出如下:
第一遍
第二遍
根据 此错误报告 计划在 JRuby 1.7 中修复。值得注意的是,虽然报告中的评论说解决方法是调用一个方法,传入一个对象实例,但似乎预先创建对象就足够了。
I don't know all the details about why this happens like it happens but I have a solution/workaround for you. (I've seen similar behaviour when passing objects that are created on the ruby side to the Java side.)
As far as I can tell JRuby needs to have already "seen" an instance of the class it is trying to unmarshal before it can get the Java-inheritance side of things right. It's almost as if creating an object within JRuby has an undocumented side-effect that registers the required inheritance hierarchy. If that isn't well worded it's because I don't understand it myself!
So the workaround is to simply create an instance of
OneClass
andTwoClass
before doing the unmarshal. If I change theself.create
method to the following:Then the output of the two passes are as follows:
First pass
Second pass
According to this bug report this is scheduled to be fixed in JRuby 1.7. It's worth noting that while the comments in the report say that the workaround is to call a method, passing an object instance in, it seems to be that the prior creation of the object is enough.