格森.JsonObject 和类加载造成了非常奇怪的情况



我有一些 maven 项目,其依赖项回到:

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
</dependency>

导致下载单个 gson-2.8.1.jar 文件。我使用"干净包"maven 构建检索此文件的副本,以便我可以引用我的 Web 应用程序动态加载的类使用的共享库的单个目录。

由于战争文件构建策略(使用"全新安装部署"maven 构建(,war 文件还在其 WEB-INF/lib 目录中获取 gson-2.8.1.jar 文件的副本。据我所知,这些都来自同一个 jar 文件。

但是,在运行 Web 应用程序并使用如下调用时:

JsonObject retVal = null;
try {
paramData.add(0, userID);
paramData.add(0, session);
retVal = (JsonObject) method.invoke(null,
paramData.toArray(new Object[0]));
} catch (Exception e) {

我得到一个奇怪的异常,例如:

"Caused by: java.lang.ClassCastException: com.google.gson.JsonObject cannot be cast to com.google.gson.JsonObject"

我不明白为什么从共享库目录中的 gson-2.8.1.jar 文件加载的相同 JsonObject 类与可能从 war文件中的 gson-2.8.1.jar 加载的 JsonObject 类不兼容。它们具有相同的大小等,并且是同一类...因为它们都来自同一个 gson-2.8.1.jar 文件......

我试图隔离类,因此只调用共享库目录中的一个 jar 文件(例如,将其从 war 文件中删除(。但是,在某些情况下,我会在尝试动态加载类时创建一个"找不到类"异常。

我意识到我的描述很难理解。从这个jar加载的JsonObject是否会导致Java认为它有两个不兼容的类,仅仅是因为它们可能是由不同的类加载器加载的,而加载的是同一个对象?

您观察到的是预期的类加载行为。 如果从两个不同的源加载相同的Foo类,从 JVM 的角度来看,它们是两个不同的类,因此不能相互强制转换(即Foo cannot be cast to Foo(。 同样,如果从两个不同的类装入器加载了相同的类Foo,则这些类加载器也不能相互强制转换。

要解决此问题,只需删除其中一个副本。 由于您已经完成了设置共享库的努力(这是首选方法(,只需通过将 maven 依赖项的范围更改为"提供",从您的应用程序 WEB-INF/lib dir 中删除 gson jar。

例如:

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
<scope>provided</scope>
</dependency>

这告诉 maven 在编译时包含此依赖项,但不在运行时包含此依赖项(因为我们知道它将由共享库提供(。

相关内容

最新更新