用自定义版本替换Java类库中的类 [英] Replace a class within the Java class library with a custom version

查看:495
本文介绍了用自定义版本替换Java类库中的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

javax / swing / plaf / basic 中的 BasicLabelUI 类受确认错误
在我的应用程序中,我需要功能修正版(提交v9)
由于法律和技术原因,我仍然受限于受影响的JDK版本。

The class BasicLabelUI in javax/swing/plaf/basic is affected by a confirmed bug. In my application I need functionality provided by the fixed version (filed for v9). Due to both legal and technical reasons, I'm still bound to the affected JDK version.

我的方法是创建一个包 javax /在我的项目中包含固定版本的swing / plaf / basic

My approach was to create a package javax/swing/plaf/basic inside my project, containing the fixed version.

如何强制我的项目支持我所包含的课程版本而不是有缺陷已安装的JDK中的类?

How can I force my project to favor my included version of the class over the defective class in the installed JDK?

这必须具有一定的可移植性,因为固定类也必须在客户端工作,并且JDK安装中的缺陷类必须是忽视。因此,我不想修改JDK,而是绕过这个特定的类。

This has to be somewhat portable as the fixed class also has to be working on customer side and the defective class in the JDK installation has to be disregarded. Therefore, I dont want to modify the JDK, but rather bypass this particular class.

推荐答案

如其他答案所述,你理论上可能当然解压缩您的JVM的 rt.jar 文件,并用兼容的bugfixed版本替换该文件。

As mentioned by the other answers, you could in theory of course unzip your JVM's rt.jar file and replace the file with a compatible bugfixed version.

引导类加载器加载任何类的Java类库,例如Swing的类,它从这个中查找它的类> rt.jar中。您通常不能将 prepend 类添加到此类路径,而无需将其添加到此文件中。有(非标准)VM选项

Any classes of the Java Class library such as those of Swing are loaded by the bootstrap class loader which looks up its classes from this rt.jar. You can generally not prepend classes to this classpath without adding them to this file. There is a (non-standard) VM option

-Xbootclasspath/jarWithPatchedClass.jar:path

您可以在其中添加包含修补版本的jar文件,但这并不一定适用于任何Java虚拟机。此外,部署更改此行为的应用程序 非法!正如官方文档中所述:

where you would prepend a jar file that includes the patched version, but this does not necessarily work on any Java virtual machine. Also, it is illegal to deploy an application that changes this hehavior! As it is stated in the official documentation:


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

Do not deploy applications that use this option to override a class in rt.jar because this violates the Java Runtime Environment binary code license.

但是如果你在引导类加载器中附加了一个类(不使用非标准的话可能会有什么)使用Instrumentation API的API,运行时仍会加载原始类,因为bootstrap类加载器在这种情况下首先搜索 rt.jar 。因此,如果不修改此文件,就不可能破坏破碎的类。

If you however appended a class to the bootstrap class loader (what is possible without using non-standard APIs by using the instrumentation API), the runtime would still load the original class as the bootstrap class loader in this case searches the rt.jar first. It is therefore impossible to "shadow" the broken class without modifying this file.

最后,它总是非法分发带有修补文件的VM ,即将其放入客户的生产系统中。许可协议明确规定您需要

Finally, it is always illegal to distribute a VM with a patched file, i.e. putting it into a production system for a customer. The license agreement states clearly that you need to


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

[...] distribute the [Java runtime] complete and unmodified and only bundled as part of your applets and applications

因此,不建议更改您分发的VM,因为在发现此情况时可能会遇到法律后果。

Changing the VM that you distribute is therefore not recommended as you might face legal consequences when this is ever uncovered.

当然,理论上您可以构建自己的OpenJDK版本,但在分发时不能再调用二进制 Java 我假设您的客户不会通过您在答案中建议的内容来实现此目的。根据经验,许多安全环境会在执行之前计算二进制值的哈希值,这会阻止两种方法调整执行的VM。

Of course, you can in theory build your own version of the OpenJDK but you could not call the binary Java anymore when you distribute it and I assume that your customer would not allow for this by what you suggest in your answer. By experience, many secure environments compute hashes of binaries before execution what would prohibit both approaches of tweaking the executing VM.

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

The easiest solution for you would probably be the creation of a Java agent that you you add to your VM process on startup. In the end, this is very similar to adding a library as a class path dependency:

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

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

A Java agent is capable of replacing a class's binary representation when the application is started and can therefore change the implementation of the buggy method.

在你的情况下,代理看起来像下面你需要将修补的类文件包含为ressource:

In your case, an agent would look something like the following where you need to include the patched class file as a ressource:

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
        }
      }
    });
  }
}

javadoc java.lang .instrumentation 包提供了有关如何构建和实现Java代理的详细说明。使用此方法,您可以使用问题类的固定版本而不违反许可协议

The javadoc java.lang.instrumentation package offers a detail description of how to build and implement a Java agent. Using this approach, you can use the fixed version of the class in question without breaking the license agreement.

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

From experience, Java agents are a great way for fixing temporary bugs in third party libraries and in the Java Class Library without needing to deploy changes in your code or even being required to deploy a new version for a customer. As a matter of fact, this is a typical use case for using a Java agent.

这篇关于用自定义版本替换Java类库中的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆