Emit
Dieses Tool unterstützt das Generieren von Bytecode für Java. Emit ist aus dem Intersult Maven Repository zu beziehen. Wesentlicher Design-Aspekt ist das einfache Benutzen und ein schlankes Paket.

Schnelle Reflection#

Die Klasse FastMethod erzeugt einen Reflection-Code, der deutlich schneller ist, als der JVM-Code:
public class FastMethodTest {
	public static final long N = 10000000000L;
	
	@Test
	public void testInvoke() throws Exception {
		FastMethod fastMethod = FastMethod.create(FastMethodTest.class, "someMethod");
		String result = (String)fastMethod.invoke(this);
		Assert.assertEquals("test-value", result);
	}
	
	public void testFastMethod() throws Exception {
		FastMethod method = FastMethod.create(FastMethodTest.class, "someMethod");
		method.invoke(this);
		long begin = System.nanoTime();
		for (long i = 0; i < N; ++i) {
			method.invoke(this);
		}
		long duration = System.nanoTime() - begin;
		System.out.println("FastMethod: " + duration / 1000000000D + " s");
	}
	public void testMethod() throws Exception {
		Method method = FastMethodTest.class.getDeclaredMethod("someMethod");
		method.invoke(this);
		long begin = System.nanoTime();
		for (long i = 0; i < 10000000000L; ++i) {
			method.invoke(this);
		}
		long duration = System.nanoTime() - begin;
		System.out.println("Method: " + duration / 1000000000D + " s");
	}
	
	public String someMethod() {
		return "test-value";
	}
}

Interceptor#

Damit kann man Klassen wrappen und Methodenaufrufe abfangen:
public class ProxyTest extends TestCase {
	public static class Test {
		private String field;
		
		public String getField() {
			return field;
		}
		public void setField(String field) {
			this.field = field;
		}
		
		@Override
		public String toString() {
			return String.valueOf(field);
		}
	}
	public static class TestInterceptor implements Interceptor {
		public Object get(Object object, String name) {
			System.out.println("interceptor getter: " + name);
			return "interceptor value";
		}
		public void set(Object object, String name, Object value) {
			System.out.println("interceptor setter: " + name + " = " + value);
		}
	}
	
	public void testCreateProxyClass() throws Exception {
		TestInterceptor testInterceptor = new TestInterceptor();
		Class<? extends Test> testProxyClass = Proxy.createProxyClass(Test.class);
		Test testProxy = testProxyClass.getConstructor(new Class[] {Interceptor.class}).newInstance(testInterceptor);
		String text = testProxy.getField();
		System.out.println(text);
		testProxy.setField("set value");
	}
}

Class Builder#

Damit kann man komplette Klassen dynamisch emittieren:
public class ClassBuilderTest extends TestCase {
	public static class TestBase {
		public String test() {
			return "Test base";
		}
	}
	
	public void testClassBuilder() throws InstantiationException, IllegalAccessException {
		ClassBuilder<TestBase> classBuilder = new ClassBuilder<TestBase>("org.ksoft.emit.builder.Test", TestBase.class);
		classBuilder.addMethod(EnumSet.of(Modifier.Public), "test", String.class).addStatement(
			new Statement.Return(
				new Statement.StringConstant("Test overwritten")
			)
		);
		TestBase test = classBuilder.newInstance();
		String string = test.test();
		System.out.print(string);
	}
}