aboutsummaryrefslogtreecommitdiffstats
path: root/tests/indy/three/Generator.java
blob: 77f1e1807d1c44b4003514fc0250595f11e5afdc (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import org.objectweb.asm.*;

public class Generator implements Opcodes {

	private String generatedRunnerTypename,linkClassName,dynMethodName,dynMethodDescriptor;
	private byte[] bytes;
	
	/**
	 * Main entry point generates a default thing, in this case a class called 'Invoker' that will use the bootstrap method on Code1 to run 'foo()'
	 * @param args
	 * @throws Throwable
	 */
	public static void main(String[] args) throws Throwable {
		Generator g = new Generator("Invoker","Code1","foo","()V");
		g.dump();
	}
	
	public byte[] getBytes() {
		return bytes;
	}

	public Generator(String generatedRunnerTypename, String linkClassName, String dynMethodName, String dynMethodDescriptor) {
		this.generatedRunnerTypename = generatedRunnerTypename;
		this.linkClassName = linkClassName;
		this.dynMethodName = dynMethodName;
		this.dynMethodDescriptor = dynMethodDescriptor;
		this.bytes = generateClass();
	}

	public void dump() {
		try {
			FileOutputStream fos
			 = new FileOutputStream(new File(generatedRunnerTypename+".class"));
			fos.write(bytes);
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public byte[] generateClass() {
		ClassWriter cw = new ClassWriter(0);
		cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, generatedRunnerTypename, null, "java/lang/Object", null);
		createConstructor(cw);
		createMain(cw);
		cw.visitEnd();
		return cw.toByteArray();
	}

	private void createMain(ClassWriter cw) {
		MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
		mv.visitCode();
		MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
				MethodType.class);
		Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, this.linkClassName, "bootstrap",
				mt.toMethodDescriptorString());
		int maxStackSize = 0;//addMethodParameters(mv);
		mv.visitInvokeDynamicInsn(dynMethodName, dynMethodDescriptor, bootstrap);
		mv.visitInsn(RETURN);
		mv.visitMaxs(maxStackSize, 1);
		mv.visitEnd();
	}
	
//	public byte[] dump(String dynamicInvokerClassName, String dynamicLinkageClassName, String bootstrapMethodName, String targetMethodDescriptor)
//			throws Exception {
//		ClassWriter cw = new ClassWriter(0);
//		cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, dynamicInvokerClassName, null, "java/lang/Object", null);
//		createConstructor(cw);
//		createMain(dynamicLinkageClassName, bootstrapMethodName, targetMethodDescriptor, cw);
//		cw.visitEnd();
//		return cw.toByteArray();
//	}



//	protected int addMethodParameters(MethodVisitor mv) {
//		return 0;
//	}


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