Code generation for alternative languages

16
Code generation for alternative languages and Java runtimes

Transcript of Code generation for alternative languages

Page 1: Code generation for alternative languages

Code generation for alternative languages

and Java runtimes

Page 2: Code generation for alternative languages

interface Framework { <T> Class<? extends T> secure(Class<T> type); }

class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } }

@interface Secured { String user(); }

class UserHolder { static String user = "ANONYMOUS"; }

does not know aboutdepends on

discovers at runtime

Page 3: Code generation for alternative languages

class Service { @Secured(user = "ADMIN") void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } // delete everything... } }

redefine class(build time, agent)

create subclass(Liskov substitution)

class SecuredService extends Service { @Override void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } super.deleteEverything(); } }

class Service { @Secured(user = "ADMIN") void deleteEverything() { // delete everything... } }

Page 4: Code generation for alternative languages

0xCAFEBABE

source code

byte code

JVM

javac scalac groovyc jrubyc

JIT compilerinterpreter

class loader

creates

reads

runs

Page 5: Code generation for alternative languages
Page 6: Code generation for alternative languages

class Sample$MockitoMock extends Sample {

@Override String getValue() { return Mockito.mock(this, new Object[0], Sample.class.getMethod("getValue")); } String original$getValue() { return super.getValue(); }

@Override void setValue(String x) { Mockito.mock(this, new Object[] { x }, Sample.class.getMethod("setValue", String.class)); } void original$setValue(String x) { super.setValue(x); } }

class Sample {

String value;

String getValue() { return value; }

void setValue(String x) { this.value = x; } }

Page 7: Code generation for alternative languages

class Sample {

var value: String? = null

fun getValue() = value

fun setValue(x: String?) { this.value = x }}

final class Sample {

String value;

final String getValue() { return value; }

final void setValue(String x) { this.value = x; } }

Page 8: Code generation for alternative languages

open class Sample {

var value: String? = null

open fun getValue() = value

open fun setValue(x: String?) { this.value = x }}

class Sample {

String value;

String getValue() { return value; }

void setValue(String x) { this.value = x; } }

Page 9: Code generation for alternative languages

<plugin> <artifactId>kotlin-maven-plugin</artifactId> <groupId>org.jetbrains.kotlin</groupId> <version>${kotlin.version}</version> <configuration> <compilerPlugins> <plugin>all-open</plugin> </compilerPlugins> <pluginOptions> <option>all-open:annotation=pkg.MyOpen</option> </pluginOptions> </configuration>

<dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-allopen</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> </plugin>

annotation class MyOpen

Page 10: Code generation for alternative languages

final class Sample {

String value;

final String getValue() { if (MockitoInfra.isMockMode(this)) { return Mockito.mock( this, new Object[0], Sample.class.getMethod("getValue")); } else { return value; } }

final void setValue(String x) { if (MockitoInfra.isMockMode(this)) { Mockito.mock( this, new Object[] { x }, Sample.class.getMethod("setValue", String.class)); } else { this.value = x; } } }

final class Sample {

String value;

final String getValue() { return value; }

final void setValue(String x) { this.value = x; } }

Page 11: Code generation for alternative languages

class MockitoInfra { static final WeakConcurrentMap<Object, MockitoHandler> mocks;

static final ThreadLocal<Boolean> selfCall;

static boolean isMock(Object instance) { return mocks.containsKey(instance); } static void registerMock(Object instance, MockHandler handler) { mocks.put(instance, handler); }

static boolean isMockMode(Object instance) { return isMock(instance) && selfCall.get(); } static void setMockMode(boolean mode) { selfCall.set(mode); } }

https://github.com/raphw/weak-lock-free

Page 12: Code generation for alternative languages

package java.lang.instrumentation;

interface Instrumentation {

void addTransformer(ClassFileTransformer transformer, boolean retransform); void retransformClasses(Class<?>... types);

void appendToBootstrapSearch(File file);

// ... }

interface ClassFileTransformer {

byte[] transform(ClassLoader loader, String name, Class<?> type, ProtectionDomain pd, byte[] buffer); }

NOPE!

Page 13: Code generation for alternative languages

Java virtual machine

[stack, JIT]

Dalvik virtual machine

[register, JIT]

Android runtime

[register, AOT]

Page 14: Code generation for alternative languages

public class SimplePlugin implements Plugin {

@Override public boolean matches(TypeDescription target) { return target.getName().equals("Foo"); }

@Override public DynamicType.Builder<?> apply( DynamicType.Builder<?> builder, TypeDescription typeDescription) { return builder.method(named("bar")) .intercept(value("Hello World!")); } }

https://github.com/raphw/byte-buddy

Page 15: Code generation for alternative languages

Build-time instrumentation with Maven.

<plugin> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-maven-plugin</artifactId> <executions> <execution> <goals> <goal>transform</goal> </goals> </execution> </executions> <configuration> <transformations> <transformation> <plugin>pkg.SimplePlugin</plugin> </transformation> </transformations> </configuration> </plugin>

Page 16: Code generation for alternative languages

http://rafael.codes@rafaelcodes

http://documents4j.comhttps://github.com/documents4j/documents4j

http://bytebuddy.nethttps://github.com/raphw/byte-buddy