我们有一个包含类Map
对象的缓存(TestClass
)。另一个类加载器再次在运行时初始化/加载TestClass
,因此在代码下方会抛出ClassCastException
:
TestClass obj1 = (TestClass)map.get("key"); // throws a ClassCastException
ClassCastException when casting to the same class
好吧,到目前为止,我确实理解这个问题。
所以,我试图找到背景信息,为什么TestClass.class
不等于TestClass.class
。我假设不同的类加载器为ReferenceType设置了不同的id?有人能向我解释背景吗?
我找到的最佳页面: http://www.objectsource.com/j2eechapters/Ch21-ClassLoaders_and_J2EE.htm
答案 0 :(得分:8)
是的,您的研究指向了正确的方向:由不同类加载器加载的相同类定义被JVM视为两个不同的类。因此,它们之间的转换失败了ClassCastException
。
我认为差异仅仅是因为游戏中有两个不同的类令牌对象。它必须是这样的,因为不同加载器加载的类实际上可能是同一类的不同版本。众所周知,每个类的类令牌都是唯一的(在同一个类加载器领域内,即)。如果JVM开始通过各种属性比较类令牌而不是通过物理相等(==
),它会打开一堆蠕虫。
答案 1 :(得分:1)
您遇到的是自定义类加载器存在的原因。它们允许在一个JVM中加载具有相同名称的不同类。 JVM中类的标识由包含类名和类加载器的元组给出。在Java语言中,只通过完全限定名称来标识类。
答案 2 :(得分:1)
有人能向我解释背景吗?
正如PéterTörök已经解释过的那样,当从不同的类加载器加载时,它们被认为是不同的。 背景是应用服务器应该能够支持不同版本的应用程序,例如您的ear-files中包含相同库的不同版本。
答案 3 :(得分:1)
没有神秘感。类型的运行时相等性在Java语言规范中定义如下:
“在运行时,具有相同二进制名称的几个引用类型可以由不同的类加载器同时加载。这些类型可能表示也可能不表示相同的类型声明。即使两个这样的类型确实表示相同的类型声明,它们被认为是截然不同的。“