有visitLdcInsn的加载对象的模拟(不固定)?(Is there an analogue o

2019-10-20 22:14发布

我们写了一个简单的Java PostScript解释,并希望通过直接对源代码的特定部分生成的字节码进行优化。 为此,我们需要从Java字节码范围内的情况下加载的对象。 在生成的字节码方法的签名指定这样的对象是不好的,因为它们可能是在我们的情况下大量。

在Java ASM,我们有方法

公共无效visitLdcInsn(对象CST)

它访问一个LDC指令。 参数CST - 不断在栈上加载。

有什么办法来加载不是恒定的对象?

谢谢

Answer 1:

由于Java 11,可以加载使用任意常数LDC指令。 这些可以是任意类型的对象,但是意在承受恒定的语义,所以它们应该优选不可变的。

对于这项工作,所引用的常量存储库项必须是一个CONSTANT_Dynamic_info ,其具有类似的结构CONSTANT_InvokeDynamic_info ,同样地描述自举方法。

一个区别是, name_and_type_index动态信息结构的条目将指向一个字段描述。 另外,自举方法具有的签名(MethodHandles.Lookup,String,Class[,static arguments])具有Class表示恒定的期望的类型,而不是一个参数MethodType对象。 自举方法直接返回恒定值,而不是调用点。

常见的invokedynamic指令是第一个引导过程的结果将得到与相关LDC指令,并在所有的后续执行中使用(因为它应该是一个常数)。

这些动态常量的一个有趣的特性是,它们是有效的静态参数为另一动态恒定或自举方法invokedynamic指令(只要有动态常数之间没有循环依赖)。

需要注意的是已经有一个方便的类包含动态常量一些准备使用的引导方法。



Answer 2:

ldc可用于类型的载荷值intfloatStringClassMethodTypeMethodHandle ; ldc2_w支持类型的值longdouble 。 1

至于说 ,Oracle的JVM实现中存在的内部使用Unsafe它允许在运行时对象作为替换为常数修补API但有几个缺点。 首先,它显然不是官方的API的一部分,而不是存在于每个JVM和未来的Oracle JVM中甚至可能会消失(或更改方法签名)。 此外,ASM框架将不知道你会做,有困难的生成以后,对补丁相应的字节码什么的。

毕竟,目前尚不清楚,滥用的优势是什么ldc在项目运行时对象应。 生成代码用于使例如作为方法或构造参数和存储的对象中的一个领域是不是很复杂与ASM。 而对于程序逻辑,也无所谓是否使用ldc或例如getstatic ,使用值权之前。



Answer 3:

作为使用的不良方式 Unsafe指出(它不是一个真正的选择要么因为它需要你以匿名方式加载的类):

我假设你正在创建过程中生成时的一类,但要注入某种运行时环境的成所需要的运行您的仪表这些类。 您可以通过编写专门的至少效仿这一ClassLoader为您的应用程序,它是意识到这一背景下,并且其明确初始化例如通过注释的类。

这意味着你的仪器类如:

@Enhanced
class Foo {

   static EnhancementDelegate delegate;

   void instrumentedMethod() {
     // do something with delegate
   }
}

在构建时,你初始化是明确在加载时间:

class EnhancementClassLoader extends ClassLoader {
  @Override
  protected Class<?> loadClass(String name) {
    Class<?> clazz = super.loadClass(name);
    if(clazz.isAnnotationPresent(Enhanced.class)) {
       // do initialization stuff
    }
    return clazz;
  }
}

这会帮助你? 这是怎样的一个猜测你正在努力实现的,但我认为这可能是一个很好的解决方案。 看看我的项目字节巴迪其通过引入解决了代理类类似的问题LoadedTypeInitializer



文章来源: Is there an analogue of visitLdcInsn for loading objects (not constant)?