【问题标题】:Loading an existing java object onto stack using ASM使用 ASM 将现有的 java 对象加载到堆栈上
【发布时间】:2015-04-30 23:00:00
【问题描述】:

我正在尝试在我的项目中使用 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 对象推送到堆栈上并避免静态调用,我就不会遇到任何性能问题。

我尝试了几种方法,但都没有运气,最后尝试了创建对象的新字段,但获得类似于此帖子的 IllegalArgumentException Creating a new field with asm 4通过链接后我意识到我们需要编写代码来创建对象并且不能直接使用现有对象。

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

【问题讨论】:

  • 您确定这实际上是一个性能瓶颈吗?您确定 JVM 没有缓存/内联它吗?
  • 嗨锑,不,我使用分析器来确定瓶颈在哪里,发现正在进行的静态调用消耗了大约 1.8%。我怎么知道缓存/内联是否完成?你的意思是这些重复静态调用需要缓存,这应该由 JVM 处理??
  • 那么 JVM 应该自动执行类似的操作。不知道为什么在这种情况下不是。
  • 我将与我认识的一些 JVM 人员核实一下。回到我的问题,所以我无法加载现有的 java 对象以避免静态调用??我的方法适配器中有一个 getter 方法这给了我 java 对象.. 有一种方法可以将它加载到我正在尝试使用 ASM 填充的当前堆栈中吗?我从您之前的回复中得知 visitLdcInsn 不会在这里工作...
  • 获取现有非常量对象的唯一方法是通过方法调用或字段访问。但如果方法或字段足够简单,无论如何都应该内联。

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


【解决方案1】:

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

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

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

根据您的方法的结构,您还可以组合这些技术(从临时本地加载,DUP 必要时,做一些不相关的事情,重复等)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多