【问题标题】:reflection between java versionsjava版本之间的反射
【发布时间】:2021-01-11 09:03:32
【问题描述】:

假设在假设的 Java 版本 X.1 中,我们在标准库(或具有向后兼容 API 且版本与 Java 版本相关的第三方)中有一个类

public class String {
    private final byte[] bytes;
    //...
}

在 Java X.2 中它在内部发生了变化

public class String {
    private final char[] chars;
    //...
}

我们还有一个访问 String 类字段的类,它是服务器插件的一部分

public class Accessor {
    public static Field getField() throws ReflectiveOperationException {
        return String.class.getDeclaredField(“bytes”);
}

服务器在 Java X.2 上运行,插件使用 Java X.1 编译并在运行时加载

会发生什么? Accessor 将看到哪个 String 类?如果它将是 X.1,那么如果服务器和插件共享一个字符串会发生什么? 如果是 X.2,有没有办法在编译时或包配置中强制使用特定版本,或者至少确定当前可见的 String 类来自哪个 Java 版本?

【问题讨论】:

    标签: java maven package javac backwards-compatibility


    【解决方案1】:

    如果我们谈论 java.lang.String 类或来自 jvm 的任何其他类,那么它通常是运行代码的 JVM 的一部分。在您的情况下,您将获得 x.2 版本。

    但是,如果我们谈论来自 3rd 方库的自定义编译类,那么它取决于在该类编译期间指定的目标版本。在您的情况下,它可能是 1.x 版。

    【讨论】:

    • 但是 JVM 如何处理在目标版本 X.1 的插件(或第三部分库)和服务器 X.2 之间共享的字符串
    • 编译时,类不存储它所依赖的其他类的信息,只存储包名和类名。因此在运行时它们都将使用 jvm 提供的版本。在你的情况下,运行时会出现一个异常,说 String 类中没有这样的成员。
    • 还有另一种方法可以加载具有相同名称和包但具有不同版本的多个类。但是对于这部分,您需要在应用程序中为每个单独的插件引入一个新的类加载器。这就是应用程序服务器(如 tomcat、jboss、glassfish 和许多其他服务器)的工作方式。最流行的实现方式是使用 osgi。
    • @AzamatZhurtbayev 但对不同版本使用不同的加载器仅适用于第 3 方库。你不能加载不同版本的java.lang.String
    • 不,JVM 通常不允许 java.lang.String 类的两个版本。否则,它就不是 JVM。
    猜你喜欢
    • 1970-01-01
    • 2015-02-11
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    相关资源
    最近更新 更多