我可以在运行时修改Java方法的字节代码吗?

时间:2013-10-09 09:26:34

标签: java proxy hook bytecode javassist

我正在编写另一个大型java程序的插件。

我想在运行时修改java程序的某些java方法的某些字节代码,这样我就可以拦截方法调用(即在方法中注入一些挂钩代码)。

任何方式都可以实现这一目标吗?

PS:

我检查了以下方法:

1.更改java程序的类加载器。 (我们不能改变它)
2.使用java代理。 (我们不能使用java代理,因为java代理会创建一个新的代理对象。我们不使用代理对象。我们需要挂钩java程序的对象,并使用该对象)
3.使用-javaagent选项(我们不能为java程序添加命令行选项。)

PS更多 [再次编辑]
我的类由ext类加载器加载(我把我的jar文件放在JAVA_HOME \ lib \ ext文件夹中)。 大型java程序是由Browser加载的applet程序。当浏览器启动applet时,它还会加载我的类。

PS更多 [再次编辑]
虽然它在Applet中运行。我可以获得完全许可。因为我可以修改java.policy和java.security文件。

谢谢,
卡尔文

4 个答案:

答案 0 :(得分:6)

只需使用-javaagent opiton,它用于在运行时修改字节码。您可以从This LinkThis Link

找到有关-javaagent的更多信息

答案 1 :(得分:2)

您可以使用多个库。请参阅示例here。 一旦类已经由VM加载/初始化,就不可能操纵它。

顺便说一句,原则上你也可以将类替换为你自己的代理类文件“钩住”。只要类的可见界面没有改变,这可能会起作用。 (虽然类的子类在运行时可能会失败。)这种替换可以像更改类路径一样简单,这样就可以在原始类之前找到同名的类。在这种情况下,委托给同名的原始类可能会稍微复杂一些。

答案 2 :(得分:2)

抱歉,但这是不可能的。首先,字节码在类加载后是不可变的。 JVM提供了几个可用于执行此类操作的API,但它们显然具有很高的特权。

如果您在浏览器Applet等低权限环境中运行,那么您显然不会被允许这样做,并且您可以将任何方法视为安全漏洞。

但问题是为什么你首先使用applet,以及为什么要在加载后修改代码。几乎可以肯定,有更好的方法可以做你想做的事情。

答案 3 :(得分:1)

是的,你可以,但这个过程会有点棘手,因为你可以直接使用内存。为此,您将查看有关sun.misc包及其Unsafe类的非官方文档。

  • 警告1:根据官方消息来源,JDK 9中将删除Unsafe类。
  • 警告2:Sun公司不会对您的代码正常工作负责,因为此类不应该使用,并且仅供系统使用。