Emitting my own jvm instructions


#1

Can someone tell me what the model is in Java derived languages such as Scala, groovy, clojure, etc when the programmer wants to control/influence the jvm instructions emmited when compiling a function? Is there some hook at the Java level for doing this, and making the resulting function/method available to the client language?


#2

It’s not really possible to influence the instructions emitted when compiling a function directly. If you want to do something like that the best approach would be to use a bytecode manipulation library like ASM. It’s a bit unpleasant to work with the JVM at this level. Here’s an example of the code you’d need to compile this Java class:

package asm;

class Example {
  public static final int anInt = 5;
}
val classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)
classWriter.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "asm/Example", null, AsmType.getInternalName(classOf[Object]), null)
classWriter.visitField(ACC_PUBLIC + ACC_STATIC + ACC_FINAL, "anInt", AsmType.INT_TYPE.getDescriptor, null, 5).visitEnd()
classWriter.visitEnd()
val classBytes = classWriter.toByteArray()

Or for something a bit more involved here’s an example of a code generator for a simple functional programming language.


#3

You might want to take a look at ByteBuddy. It implements a builder-pattern DSL for generating bytecode at runtime. For example (Java):

Class<?> dynamicType = new ByteBuddy()
  .subclass(Object.class)
  .method(ElementMatchers.named("toString"))
  .intercept(FixedValue.value("Hello World!"))
  .make()
  .load(getClass().getClassLoader())
  .getLoaded();

#4

Could you explain what your use case is?

It is difficult to insert your own bytecode into a class compiled from source code, because modern compilers analyze the dataflow and regularly rearrange steps to make it more efficient, making it hard to meaningfully specify a point where to insert custom bytecode or making sure it works as expected.

If you want to provide your own bytecode, rather than trying to convince the compiler to insert it for you, you probably want to put it into an extra class that is not compiled by a compiler at all, but created entirely by you, and then loaded it using a custom class loader. This is what the other posters are suggesting.