【问题标题】:How to cast two instance of the same loaded different classloader?如何强制转换相同加载的不同类加载器的两个实例?
【发布时间】:2012-05-21 03:32:43
【问题描述】:

我有两个不同的网络应用程序,每个应用程序都使用不同的类加载器加载相同的 A 类。当我将一个实例放入会话中,然后从另一个 web 应用程序中获取它时,会抛出一个 ClassCastException

例如,在 webapp A 中,我将 a 存储在 session 中,然后在 webapp B 中,我从 session 中获取 a 并将其转换为 A,ClassCastException 被抛出。

有没有办法解决这个问题?

【问题讨论】:

    标签: java tomcat web-applications classcastexception


    【解决方案1】:

    有没有办法解决这个问题?

    基本没有。

    就 JLS 而言,类型是不同的类型,JVM 不会允许您假装其他类型。例如,类可能有不同的代码和不同的对象布局。如果您可以欺骗 JVM 将类型视为相同,您将能够吹走 JVM 运行时安全性。那样就是精神错乱。

    解决方案是确保您没有两个不同的类加载器加载同一个类。在 Tomcat 的上下文中,这意味着如果两个或多个 webapps 需要共享一个类的实例,那么该类必须定义在一个对两者都通用的类加载器中;例如将 JAR 文件放在 $CATALINA_HOME/lib$CATALINA_HOME/common 目录中。


    如果出于技术原因必须由不同的类加载器加载类(可能是因为类确实不同),那么您可以通过定义两个版本的接口来解决该问题类实现,然后编程到接口而不是实现类。当然,接口需要通过共享类加载器来加载……否则你又会遇到同样的问题。

    【讨论】:

      【解决方案2】:

      这可以通过解决方法来实现。

      虽然您确实不能将对象从类加载器 A 加载的一个类转换为类加载器 B 加载的同一个类(如果在不同的类加载器下加载相同名称的类,则不兼容 explained here),在 Jetty 或 Tomcat 等 webapp 容器中,您可以在父类加载器中加载该类一次,该类将由 JVM 中的所有 webapps 使用。每个 webapp 类加载器都将遵循共享(父)类加载器的类定义,并且来回转换它就可以了。

      例如,对于 Jetty,使用 WebAppContext.addSystemClass(),如 here 所述。

      【讨论】:

        【解决方案3】:

        即使类具有相同的包名和签名,您也不​​能从不同的类中转换两个对象,但是您可以使用 apache bean utils 库将数据从一个对象复制到另一个对象,BeanUtils.copyProperties(o1, o2);

        【讨论】:

          【解决方案4】:

          也许你可以序列化共享对象?

          我不一定提倡这种方法,但这就是序列化本质上所做的——你从一些 JVM 或 ClassLoader X 序列化并将其加载(反序列化)到另一个 JVM/类加载器 Y...

          【讨论】:

          • 我认为序列化可能会起作用,但我最终使用CAS解决了这个问题。 :)
          • @xiaolg2008 - 你指的是什么 CAS?
          【解决方案5】:

          你不能。不同类加载器加载的两个类是不同的。

          【讨论】:

            【解决方案6】:

            您应该避免这种情况,基本上 - 要么将两个功能放在同一个 webapp 中,要么将包含类 A 的库移动到适当的位置,以便只使用一个类加载器。由不同类加载器加载的两个类在 JVM 中是完全不同的——您只是无法在它们之间进行转换。

            有关所使用的各种类加载器的更多详细信息,请参阅Tomcat classloader documentation。看起来您希望将这个公共类放入公共类加载器区域。正如文档所述,这很不寻常,但如果您真的想在两个 web 应用程序之间共享一个对象(这不寻常),这可能是最简单的方法。

            【讨论】:

              猜你喜欢
              • 2023-03-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-28
              • 2018-03-14
              • 2018-04-01
              相关资源
              最近更新 更多