Is there an analogue of visitLdcInsn for loading o

2019-08-11 11:22发布

We wrote a simple PostScript interpreter in Java and want to optimize it by generating bytecode directly for specific parts of source code. For this we need to load the object from the context of the Java bytecode context. Specify such object in the signature of the generated bytecode method is not good, because they may be in a large amount in our case.

In Java Asm we have method

public void visitLdcInsn(Object cst)

It visits a LDC instruction. Parameter cst - the constant to be loaded on the stack.

Is there any way to load not constant object?

Thanks

3条回答
叼着烟拽天下
2楼-- · 2019-08-11 11:50

ldc can be used for loading values of type int, float, String, Class, MethodType or MethodHandle; ldc2_w supports values of type long and double. 1

As said, within Oracle’s JVM implementation there is the internally used Unsafe API which allows patching in runtime objects as replacements for constants but that has several drawbacks. First, it’s obviously not part of the official API, not present in every JVM and might even disappear (or change method signatures) in future Oracle JVMs. Further, the ASM framework will not be aware of what you are going to do and have difficulties to generate the appropriate bytecode for later-on patches.

After all, it’s not clear, what the advantage of abusing ldc for a runtime object in your project shall be. Generating the code for passing the instance as method or constructor parameter and storing an object in a field is not very complicated with ASM. And for the program logic, it doesn’t matter whether you use ldc or, e.g. getstatic, right before using the value.

查看更多
放我归山
3楼-- · 2019-08-11 12:02

As the bad way of using the Unsafe was pointed out (it is not really an option either as it requires you to load the classes anonymously):

I assume that you are creating a class during build time but you want to inject some sort of runtime context into these classes which are required for running your instrumentation. You can at least emulate this by writing a specialized ClassLoader for your application which is aware of this context and which explicitly initializes a class by for example an annotation.

This means you instrument a class such as:

@Enhanced
class Foo {

   static EnhancementDelegate delegate;

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

at build-time and you initialize is explicitly at load time:

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;
  }
}

Would this help you out? It is kind of a guess what you are trying to achieve but I think this might be a good solution. Check out my project Byte Buddy which solves a similar problem for proxy classes by introducing a LoadedTypeInitializer.

查看更多
虎瘦雄心在
4楼-- · 2019-08-11 12:08

Since Java 11, it is possible to load arbitrary constants using the LDC instruction. These may be objects of arbitrary type but meant to bear constant semantics, so they should be preferably immutable.

For this to work, the referenced constant pool entry has to be a CONSTANT_Dynamic_info, which has a similar structure as the CONSTANT_InvokeDynamic_info, likewise describing a bootstrap method.

One difference is that the name_and_type_index entry of the dynamic info structure will point to a field descriptor. Further, the bootstrap method has a signature of (MethodHandles.Lookup,String,Class[,static arguments]) having a Class argument representing the expected type of the constant, rather than a MethodType object. The bootstrap method has to directly return the constant value rather than a call-site.

Common to the invokedynamic instruction is that the result of the first bootstrapping process will get associated with the LDC instruction and used in all subsequent executions (as it is supposed to be a constant).

An interesting property of these dynamic constants is that they are valid static arguments to the bootstrap method for another dynamic constant or an invokedynamic instruction (as long as there is no cyclic dependency between the dynamic constants).

Note that there is already a convenience class containing some ready-to-use bootstrap methods for dynamic constants.

查看更多
登录 后发表回答