aboutsummaryrefslogtreecommitdiffstats
path: root/tests/bugs198/github_68/Generator.java
blob: ea34c5b3b8005671eb5033d44153a6d94d9c4bfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * This class was created by ASM-ifying a class generated by Byte Buddy.
 * Its purpose it to create a class <tt>CondyCallable</tt> making use of
 * dynamic class-file constants, a Java 11 feature introduced by JEP 309.
 *
 * @see https://openjdk.java.net/jeps/309
 */
public class Generator implements Opcodes {

  private static final String CLASS_FILE = "CondyCallable.class";

  public static void main(String[] args) throws IOException {
    try (FileOutputStream fos = new FileOutputStream(CLASS_FILE)) {
      fos.write(getClassBytes());
    }
    System.out.println(CLASS_FILE + " generated successfully");
  }

  private static byte[] getClassBytes() {
    ClassWriter classWriter = new ClassWriter(0);
    classWriter.visit(V11, ACC_PUBLIC | ACC_SUPER, "CondyCallable", null, "java/lang/Object", new String[] { "java/util/concurrent/Callable" });
    createDefaultConstructor(classWriter);
    createMethod_call(classWriter);
    classWriter.visitEnd();
    return classWriter.toByteArray();
  }

  private static void createDefaultConstructor(ClassWriter classWriter) {
    MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    methodVisitor.visitCode();
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
    methodVisitor.visitInsn(RETURN);
    methodVisitor.visitMaxs(1, 1);
    methodVisitor.visitEnd();
  }

  private static void createMethod_call(ClassWriter classWriter) {
    MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "call", "()Ljava/lang/Object;", null, new String[] { "java/lang/Exception" });
    methodVisitor.visitCode();
    methodVisitor.visitLdcInsn(
      // Create constant-dynamic instruction
      new ConstantDynamic(
        // Dummy name
        "_",
        // Constant type
        "LApplication;",
        // Bootstrap method: ConstantBootstraps::invoke, dispatching to an existing method/constructor
        new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/ConstantBootstraps", "invoke", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;", false),
        // Bootstrap method arguments: here we simply dispatch to the constructor of class Application
        new Handle(Opcodes.H_NEWINVOKESPECIAL, "Application", "<init>", "()V", false))
    );
    methodVisitor.visitInsn(ARETURN);
    methodVisitor.visitMaxs(1, 1);
    methodVisitor.visitEnd();
  }

}