您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

用自定义版本替换Java类库中的类

用自定义版本替换Java类库中的类

正如其他的答案中提到,您 在过程中解压缩到JVM的理论 rt.jar的 文件,并兼容bugfixed版本替换该文件

引导类加载器 会加载java类库的所有类(例如Swing的 类),该类加载器 会从 rt.jar 查找其类。如果不将类添加到此文件中,通常不能将它们添加到 路径中。有(非标准)VM选项

-Xbootclasspath/jarWithPatchedClass.jar:path

您可能会在其中添加一个包含修补程序版本的jar文件,但这在任何Java虚拟机上都不一定有效。另外, 更改此行为 也是 !如官方文档中所述

不要部署使用此选项覆盖rt.jar中的类的应用程序,因为这违反了Java Runtime Environment二进制代码许可证。

但是,如果您将一个类附加到引导类加载器(通过使用仪表API不使用非标准API的情况下可以实现),则运行时仍会加载原始类,因为引导类加载器在这种情况下首先搜索rt.jar 。因此,如果不修改文件就无法“遮盖”损坏的类。

最后,分发带有补丁文件的VM(即将其放入客户的生产系统中)始终是非法的。许可协议明确指出您需要

[…]完整且未经修改地分发[Java运行时],仅捆绑为小程序和应用程序的一部分

因此,不建议更改分发的VM,因为一旦发现它,您可能会面临法律后果。

当然,从理论上讲,您可以构建自己的OpenJDK版本,但是在分发二进制 Java 时,您再也不能调用它了,并且我认为您的客户在您的回答中所建议的不允许这样做。根据经验,许多安全环境会在执行之前计算二进制哈希,这将阻止两种方法来调整正在执行的VM。

对您而言,最简单的解决方案可能是创建一个Java代理,然后在启动时将其添加到VM进程中。最后,这与将库添加为类路径依赖项非常相似:

java -javaagent:bugFixAgent.jar -jar myApp.jar

启动应用程序时,Java代理能够替换类的二进制表示形式,因此可以更改越野车方法的实现。

在您的情况下,代理将如下所示,您需要将修补的类文件作为资源包括在内:

public static class BugFixAgent {
  public static void premain(String args, Instrumentation inst) {
    inst.addClassFileTransformer(new ClassFileTransformer() {
      @Override
      public byte[] transform(ClassLoader loader, 
                              String className, 
                              Class<?> classBeingredefined, 
                              ProtectionDomain protectionDomain, 
                              byte[] classfileBuffer) {
        if (className.equals("javax/swing/plaf/basic/BasicLabelUI")) {
          return patchedClassFile; // as found in the repository
          // Consider removing the transformer for future class loading
        } else {
          return null; // skips instrumentation for other classes
        }
      }
    });
  }
}

javadocjava.lang.instrumentation软件包提供了有关如何构建和实现Java代理的详细描述。使用这种方法,您可以使用相关类的固定版本, 。

从经验来看,Java代理是修复第三方库和java类库中的临时错误的好方法,而无需部署代码中的更改,甚至不需要为客户部署新版本。实际上,这是使用Java代理的典型用例。

java 2022/1/1 18:14:49 有483人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶