【问题标题】:gson.JsonObject and class loading creating very odd situationsgson.JsonObject 和类加载创建非常奇怪的情况
【发布时间】:2017-07-18 01:22:16
【问题描述】:

我有一些 maven 项目的依赖项返回到:

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

导致下载单个 gson-2.8.1.jar 文件。我使用“clean package” maven build 检索此文件的副本,因此我可以为我的 Web 应用程序动态加载的类所使用的共享库引用单个目录。

由于 war 文件构建策略(使用“clean install deploy”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 类与可能从 gson-2.8.1.jar 加载的 JsonObject 类不兼容在战争文件中。它们具有相同的大小等,并且是相同的类...因为它们都源自同一个 gson-2.8.1.jar 文件...

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

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

【问题讨论】:

    标签: java maven gson code-injection websphere-liberty


    【解决方案1】:

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

    要解决此问题,只需删除其中一个副本即可。由于您已经完成了设置共享库的工作(这是首选方法),只需通过将 maven 依赖项的范围更改为 `provided.

    例如:

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

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

    【讨论】:

    • 感谢您的详细解释。这是完全有道理的。我取消并回滚了更改,只在 OpenWhisk 所需的方法中添加了 JsonObject,并从那里转换为 JSONObject,以减少对 JsonObject 的依赖,仅从共享库目录加载 gson-2.8.1.jar 的一个类。但我可能会尝试恢复以前的代码,看看这会奏效。我认为我相当于将 jar 从战争文件中移出是等价的。它可能不起作用,因为 jar 是为战争加载的,并且是由注入的类加载的,所以 !=classloader
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多