使用ASM将现有java对象加载到堆栈上

时间:2013-10-07 07:53:39

标签: java bytecode java-bytecode-asm bytecode-manipulation

我正在尝试将ASM用于我的项目并遇到一个性能问题,我试图使用静态方法获取所需对象并将其调用为1000次

visitor.visitMethodInsn(Opcodes.INVOKESTATIC, TrackingConstants.TO_HELPER_CLASS, "getRTTDObject",TrackingConstants.TO_HELPER_GET_CLIENT_METHOD_DESC);

visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, TrackingConstants.CLIENT_INTERFACE_CLASS, "getPattern",TrackingConstants.CLIENT_INTERFACE_CLASS_GETPATTERN_METHOD_DESC);     

这第一次调用导致我开销(我获得所需的对象并传递到下一行,用于在对象上执行“getPattern”。在调查过程中,我意识到我试图通过静态方法检索的对象可用于我从开始本身,所以如果我能够将Java对象推入堆栈并避免静态调用我不会遇到任何性能问题。

我尝试了几种没有运气的方法,最后试图创建对象的新Field,但得到类似于这篇文章的IllegalArgumentException Creating a new field with asm 4经过链接后我意识到我们需要编写代码来创建对象,而不能直接使用现有对象。

所以我无法将现有的Java对象加载到堆栈上(我猜它已经在堆栈上,有没有办法可以使用它)并执行所需的操作而不是使用静态调用来获取它?有没有办法实现呢?

1 个答案:

答案 0 :(得分:1)

一旦对象在堆栈上(大概是在你第一次调用静态方法之后),你可以:

  1. 每次需要时,发出DUP指令以复制堆栈上已有的值。这可能是性能最高的选项,但它要求您以这样的方式制作字节码,使得值在您需要时始终位于堆栈顶部/附近。有DUP指令的一些变体可供选择,每种都有不同的行为;有关详细信息,请参阅JVM Specification §6.5

  2. 调用静态方法一次,然后将结果存储在临时变量中(使用ASTORE指令变体之一)。在需要时使用相应的ALOAD变体将其推入堆栈。

  3. 根据您的方法的结构,您还可以结合使用这些技术(根据需要从临时本地加载DUP,执行不相关的操作,重复等)。