Fab*_*non 22 java runtime classloader javassist playframework
我想在运行时替换一些方法的内容.
我知道我可以使用javassist但它不起作用,因为我想要增强的类已经被系统classLoader加载.
我该怎么做,在运行时替换方法的内容?我应该尝试卸载课程吗?我怎样才能做到这一点 ?我看到它是可能的,但我无法弄清楚如何做到这一点.
如果可能的话,我想避免使用外部库,我想自己编写代码.
更多信息: - 我想要增强的类包含在一个框架中(在一个jar文件中) - 我的代码实际上是这个框架的一个插件 - 我的插件运行的框架有自己的classLoader,但是这个classLoader没有加载自己的类(它将它们委托给系统类加载器) - 我正在使用的框架是Play.
谢谢您的帮助 !
您可以使用Javaassist以及其他任何字节码工程库来实现.神奇之处在于Java Attach API,它允许程序附加到正在运行的JVM(并修改加载的类).
它可以在com.sun.tools.attach包中找到,顾名思义,它特定于Oracle JVM.尽管如此,JDK工具喜欢jstack并jmap使用它来支持它们"附加到运行JVM"功能,因此可以肯定地说它就在这里.
Attach API上的文档具有相当的描述性,本Oracle博客文章演示了如何在运行时附加代理.一般来说,它归结为:
-javaagent用" premain等" 方式使转换程序成为"常规" 方式premain为agentmainAgent-Class您的代理(agentmain-containing)类的清单,并Can-Retransform-Classes设置为true值得庆幸的是,API可以在您没有太多工作的情况下执行此操作,但是如果您在运行时执行JAR生成,则打包代理所需的所有类可能有点棘手.
我希望包含一个演示代理,演示在运行时附加一个分析器,但它最终过于冗长而无法发布.尽管如此,我还是把它放在了Github的回购中.
这种方法的一个警告是,它使您的程序依赖于tools.jarJDK附带的程序,而JRE中不存在该程序.您可以通过tools.jar附带(或提取)应用程序来解决此问题,但您仍需要在应用程序中提供attachAttach API所需的本机库.我已经在上面链接的存储库中找到了我可以找到的所有平台的库,尽管你也可以自己获取它们.
根据您的使用情况,这可能是也可能不是理想的.但它确实有效!
这个问题并不清楚,但是如果您想要做的是在运行时使用您自己的类完全"热交换"类,则不需要使用任何字节码操作库.相反,您可以单独编译您的类(确保相同的包,类名等),并transform在目标类上调用时返回新类的字节.
普通的类加载器不支持在定义类后取消定义或修改类。因此,插件无法修改框架的行为,除非该框架提供了此类自定义的挂钩。
您可以创建一个自定义类加载器,从其父类加载器中隐藏一些类,然后重新定义它们,添加您可能需要的任何工具。但框架在插件之前加载,并将使用其自己的类加载器解析类。因此它将继续使用这些类的未检测版本。
避免这种情况的唯一合理方法(我能想到的)是首先出现:如果您的代码首先启动,它可以引入一个类加载器用于加载框架。但这意味着您必须有某种方法将代码作为框架的包装器放入链中。不确定这对于您的情况是否可行。
回复评论更新:
为了创建一个包含某些类的类加载器,您必须重写它的loadClass方法。如果您的许可允许使用 GPL 代码,您可以查看OpenJDK在默认实现中如何执行此操作。对于那些不想隐藏的类,您只需遵循父类加载器即可。
隐藏父版本后,您仍然需要修改该类。也许BCEL 类加载器可以帮助您。或者从包含修改版本的 jar 文件加载该类。或者类似的东西。
| 归档时间: |
|
| 查看次数: |
7256 次 |
| 最近记录: |