是否可以确定Java类对象在虚拟机中的位置是相同的

是否可以确定Java类对象在虚拟机中的位置是相同的,java,class,identification,Java,Class,Identification,我有许多在不同机器上运行的特定程序的实例。除了安装新版本的停机时间外,程序一直在运行,并且在安装期间,不同版本的程序可以在不同的机器上运行。但由于有这么多不同的安装,我希望确保从类的特定运行生产者的一个类定义序列化的数据(有效地)与数据接收方的类定义相同 因此,显而易见的解决方案是使用SerialVerionID,但更改会破坏其他内容,人们可能会忘记更新之间的ID,而这在类对象本身(object.getClass())中是不可用的。System.identityHashcode()也没有任何价值

我有许多在不同机器上运行的特定程序的实例。除了安装新版本的停机时间外,程序一直在运行,并且在安装期间,不同版本的程序可以在不同的机器上运行。但由于有这么多不同的安装,我希望确保从类的特定运行生产者的一个类定义序列化的数据(有效地)与数据接收方的类定义相同

因此,显而易见的解决方案是使用SerialVerionID,但更改会破坏其他内容,人们可能会忘记更新之间的ID,而这在类对象本身(object.getClass())中是不可用的。System.identityHashcode()也没有任何价值


因此,我想真正的问题是,如果有人递给你一个类对象,并且你引用了预期的类对象,是否有办法判断这两个类是否完全代表相同的对象、字段、字段定义等。即使类具有完全相同的包和名称,你也可以这样做。但它也有缺点,您可以使用反射来检查对象的所有属性、方法和内部结构,并将其与另一个对象进行比较以检查是否等效

Class c = ob.getClass();
for (Method method : c.getMethods()) {
  if (method.getAnnotation(PostConstruct.class) != null) {
    System.out.println(method.getName());
  }
}
这就是方法

您可以对字段执行相同的操作:

Field[] allFields = SomeClass.class.getDeclaredFields();

然后可以检查它们是否是类的同一版本。如果方法或字段的数量不同,但是如果更改在方法内部,则无法轻松区分una类和其他类。

您可以比较类的
.class
文件中字节的
hashCode()
,因为类已加载,所以可以使用该类

下面是一些获取散列的代码:

public static int getHash(Class<?> clazz) throws IOException {
    return Arrays.hashCode(clazz.getClassLoader().getResourceAsStream(clazz.getName().replace(".", "/")).readAllBytes());
}
publicstaticintgethash(类clazz)抛出IOException{
返回Arrays.hashCode(clazz.getClassLoader().getResourceAsStream(clazz.getName().replace(“.”,“/”).readAllBytes());
}

在这种情况下,所有可用的都是类对象,而不是/a类的实例。答案不是为此使用Java序列化,而是显式支持转发兼容性的协议-例如Protobuf、Avro、FlatBuffers等。类的版本可以反序列化,那么就没有理由检查它是否相同。如果类的版本无法反序列化,则无法检查它是否相同。不确定你的建议是否太有用…@Camilo你的代码确实可以工作,但因为它涉及到反射,所以成本很高。我可能最终不得不使用你的方法。@BoristheSpider在我的例子中,通过网络发送的是类,而不是类的实例。但是你的建议仍然很好。我想知道什么样的更改会影响哈希值——例如,重构以重新排列字段声明顺序会改变哈希值吗?似乎它最终会遇到与不声明
SerialVerionId
@Boris同样的问题,这是极不可能的。散列依赖于字节顺序,如
String#hashCode()
。我的理解是hashcode()是一个与类的内容相关的数字,而不是类的定义。因此,哈希代码所要做的就是确保两个实例的内容相同。我说得对吗?目的是确保在比较两个同名的类时,类定义是相同的。@allan您不正确。此代码比较类的字节码(“定义”)的哈希代码。您可以将此哈希代码传递到导线上,并在另一端进行比较。当您使用短语“类的内容”时,我认为您的意思是“类的实例的内容”,这是hashcode的通常用途。在本例中,“实例”是一个包含类定义的
字节[]
。@Bohemian我认为你是错误的。例如,假设我有两个字符串对象,一个包含“A”,另一个包含“B”。每个的hashcode不同,但定义相同。哈希代码基于实例的内容,而不是实例的定义。