[英]How to inject a class into the java.lang package
当尝试通过OpenJDK 11上的java.lang.instrument.Instrumentation#appendToBootstrapClassLoaderSearch
注入java.lang
命名空间中的类时,没有任何反应并且不会引发错误。 将类放入注入不同的包时,它按预期工作。
JarFile jar = new JarFile(new File("file/to/bootstrap.jar));
instrumentation.appendToBootstrapClassLoaderSearch(jar);
// throws ClassNotFoundException java/lang/Dispatcher
Class.forName("java.lang.Dispatcher", false, null);
bootstrap.jar
└─ java/lang/Dispatcher.class
我想这样做的原因是为了克服一些OSGi容器的问题。 它们通常将对bootstrap类加载器的委派限制为仅限于某些包。 默认情况下,显然总是包含java.*
这就是为什么我想把Dispatcher
类放在那里。 我知道org.osgi.framework.bootdelegation
但该属性仅在初始化期间被读取。 这意味着在运行时附加代理时,覆盖此值已经太晚了。
另一种方法是检测所有已知的OSGi类加载器并将代理类列入白名单。 但是为每个框架执行此操作并测试每个版本似乎不太可行。
如何将自定义类(如java.lang.Dispatcher
注入引导类加载器? 是否有其他模式或最佳实践来避免OSGi bootdelegation问题?
提供更多背景信息:
我的想法是只将这个Dispatcher
类注入bootstrap类加载器。 调度程序基本上只包含一个静态Map。 代理程序的其余类将由专用的URLClassLoader加载,该类是引导类加载器的子代。 然后代理将在调度程序的Map中注册MethodHandle
,以便注入的字节代码可以获得MethodHandles,它允许访问代理程序类加载器中加载的代理程序的类。
可以使用不安全的API。 从Java 9开始,引导类加载器的实现已更改为仅检查已指定包的指定jmod,但不再检查引导搜索路径。
Java的11也去掉了sun.misc.Unsafe#defineClass
方法,但同样的方法仍然可用在jdk.internal.misc.Unsafe
。
你必须打开该类的内部模块。 您可以使用sun.misc.Unsafe
执行此操作,它允许您编写字段值( accessible
)而无需可访问性检查或使用Instrumentation的官方API。
如果您正在使用Byte Buddy,请查看为所有方法提供实现的ClassInjector
实现。
有一个开放的票据可以解释Java代理注入帮助程序类的需要,但在解决之前,这是一个常见的解决方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.