Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Making Java more dynamic:
runtime code generation
for the JVM
interface Framework {
<T> Class<? extends T> secure(Class<T> type);
}
class Service {
@Secured(user = "ADMIN")
void delete...
class Service {
@Secured(user = "ADMIN")
void deleteEverything() {
if(!"ADMIN".equals(UserHolder.user)) {
throw new Illega...
0xCAFEBABE
source code
byte code
JVM
javac scalac groovyc jrubyc
JIT compilerinterpreter
class loader
creates
reads
runs
class Method {
Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
Invocati...
Do-it-yourself as an alternative?
class Service {
void deleteEverything() {
if(!"ADMIN".equals(UserHolder.user)) {
throw n...
The “black magic” prejudice.
var service = {
/* @Secured(user = "ADMIN") */
deleteEverything: function () {
// delete ever...
The performance myth.
int compute() {
return i * ConstantHolder.value;
}
There is no point in “byte code optimization”.
It...
int foo() {
return 1 + 2;
}
ICONST_1
ICONST_2
IADD
operand stack 1
2
13
IRETURN
0x04
0x05
0x60
0xAC
Java source code Java ...
MethodVisitor methodVisitor = ...
methodVisitor.visitInsn(Opcodes.ICONST_1);
methodVisitor.visitInsn(Opcodes.ICONST_2);
me...
• Byte code-level API gives full freedom
• Requires knowledge of byte code
(stack metaphor, JVM type system)
• Requires a ...
ASM / BCEL Javassist cglib Byte Buddy
int foo() {
return 1 + 2;
}
"int foo() {" +
" return 1 + 2;" +
"}"
• Strings are not...
class SecuredService extends Service {
@Override
void deleteEverything() {
methodInterceptor.intercept(this,
Service.class...
ASM / BCEL Javassist cglib Byte Buddy
• Discards all available type information
• JIT compiler struggles with two-way-boxi...
ASM / BCEL Javassist cglib Byte Buddy
Class<?> dynamicType = new ByteBuddy()
.subclass(Object.class)
.method(named("toStri...
ASM / BCEL Javassist cglib Byte Buddy
class MyInterceptor {
static String intercept() {
return "Hello World";
}
}
identifi...
ASM / BCEL Javassist cglib Byte Buddy
Annotations that are not visible to a class loader are ignored at runtime.
Thus, Byt...
ASM / BCEL Javassist cglib Byte Buddy
@Origin Method|Class<?>|String Provides caller information
@SuperCall Runnable|Calla...
ASM / BCEL Javassist cglib Byte Buddy
class Foo {
String bar() { return "bar"; }
}
Foo foo = new Foo();
new ByteBuddy()
.r...
class Foo {
String bar() { return "bar"; }
}
assertThat(new Foo().bar(), is("Hello World!"));
public static void premain(S...
class TimerAdvice {
@OnMethodEnter
static long enter() {
return System.nanoTime();
}
@OnMethodExit
static void exit(@Enter...
class Foo {
String bar() { return "bar"; }
}
System.out.println(new Foo().bar());
public static void agentmain(String argu...
Build-time instrumentation: API
public class SimplePlugin implements Plugin {
@Override
public boolean matches(TypeDescrip...
Build-time instrumentation with Maven.
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</arti...
Build-time instrumentation with Maven.
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</arti...
Build-time instrumentation with Gradle.
buildscript {
repositories { jCenter() }
dependencies {
classpath "net.bytebuddy:b...
Reality check: Reinvent Java?
“Plain old Java applications” (POJAs)
Working with POJOs reduces complexity. Reducing infras...
Java virtual
machine
[stack, JIT]
Dalvik virtual
machine
[register, JIT]
Android
runtime
[register, AOT]
Android makes thi...
baseline Byte Buddy cglib Javassist Java proxy
(1) 0 142 515 193 70
(2a) 0 1‘126 960 1’070 1’060
(2b) 0.002 0.002 0.003 0....
I O
foo()
bar()
qux()
Performance: delegation vs. advice
foo()
bar()
qux()
qux()
intercept()
-XX:MaxInlineSize=35 (auto-re...
foo()
[module A]
bar()
[module A]
qux()
[module A]
qux()
[module A]
intercept()
[module B]
Module moduleA = findModule("A"...
Loading and leaking runtime classes
boot extension system wrapper
Foo
Bar
[wrapper]
Bar
[inject]
public class Foo {
/* pac...
Caching runtime classes
WeakHashMap<Class<?>, Class<?>> proxies;
Foo Foo$Proxy
via CL
WeakHashMap<Class<?>, SoftReference<...
class Foo {
void bar(Object arg) { /* do something */ }
}
class Bar extends Foo {
@Override
void bar(Number arg) { /* do s...
class Foo {
public void bar() { /* do something */ }
}
public class Bar extends Foo {
/* bridge */
public void bar() { sup...
Generic runtime types and dealing with meta data
new ByteBuddy()
.subclass(parameterizedType(Bar.class,
String.class).buil...
class $MethodProxy implements MethodProxy {
@Override
public Object invokeSuper(Object self,
Method method,
Object[] argum...
class $BarMethodProxy implements Runnable {
final Foo self; final int arg; // constructor omitted
@Override
public void ru...
Problems caused by “optional” types
class SomeFramework {
void doFrameworkStuff() {
if (isFancyPluginAvailable()) {
init(n...
Not requiring loaded types: an reflection API alternative
interface TypeDescription
interface MethodDescription
interface ...
http://rafael.codes
@rafaelcodes
http://documents4j.com
https://github.com/documents4j/documents4j
http://bytebuddy.net
ht...
Making Java more dynamic: runtime code generation for the JVM
Upcoming SlideShare
Loading in …5
×
Upcoming SlideShare
Take a Look at Akka+Java (English version)
Next
Download to read offline and view in fullscreen.

26

Share

Download to read offline

Making Java more dynamic: runtime code generation for the JVM

Download to read offline

While Java’s strict type system is a great help for avoiding programming errors, it also takes away some of the flexibility that developers appreciate when using dynamic languages. By using runtime code generation, it is possible to bring some of this flexibility back to the Java virtual machine. For this reason, runtime code generation is widely used by many state-of-the-art Java frameworks for implementing POJO-centric APIs but it also opens the door to assembling more modular applications. This presentation offers an introduction to the complex of runtime code generation and its use on the Java platform. Furthermore, it discusses the up- and downsides of several code generation libraries such as ASM, Javassist, cglib and Byte Buddy.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Making Java more dynamic: runtime code generation for the JVM

  1. 1. Making Java more dynamic: runtime code generation for the JVM
  2. 2. 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 discoversatruntime
  3. 3. 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... } }
  4. 4. 0xCAFEBABE source code byte code JVM javac scalac groovyc jrubyc JIT compilerinterpreter class loader creates reads runs
  5. 5. class Method { Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; } class Class { Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException; } Isn’t reflection meant for this? Reflection implies neither type-safety nor a notion of fail-fast. Note: there are no performance gains when using code generation over reflection! Thus, runtime code generation only makes sense for user type enhancement: While the framework code is less type safe, this type-unsafety does not spoil the user‘s code.
  6. 6. Do-it-yourself as an alternative? class Service { void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } // delete everything... } } At best, this makes testing an issue. Maybe still the easiest approach for simple cross-cutting concerns. In general, declarative programming often results in readable and modular code.
  7. 7. The “black magic” prejudice. var service = { /* @Secured(user = "ADMIN") */ deleteEverything: function () { // delete everything ... } } function run(service) { service.deleteEverything(); } In dynamic languages (also those running on the JVM) this concept is applied a lot! For framework implementors, type-safety is conceptually impossible. But with type information available, we are at least able to fail fast when generating code at runtime in case that types do not match. No type, no problem. (“duck typing”)
  8. 8. The performance myth. int compute() { return i * ConstantHolder.value; } There is no point in “byte code optimization”. It’s not true that “reflection is slower than generated code”. Method::invoke NativeMethodAccessor GeneratedMethodAccessor### The JIT compiler knows its job pretty well. NEVER “optimize” byte code. Never use JNI for something you could also express as byte code. However, avoid reflective member lookup. -Dsun.reflect.inflationThreshold=#
  9. 9. int foo() { return 1 + 2; } ICONST_1 ICONST_2 IADD operand stack 1 2 13 IRETURN 0x04 0x05 0x60 0xAC Java source code Java byte code
  10. 10. MethodVisitor methodVisitor = ... methodVisitor.visitInsn(Opcodes.ICONST_1); methodVisitor.visitInsn(Opcodes.ICONST_2); methodVisitor.visitInsn(Opcodes.IADD); methodVisitor.visitInsn(Opcodes.IRETURN); MethodNode methodNode = ... InsnList insnList = methodNode.instructions; insnList.add(new InsnNode(Opcodes.ICONST_1)); insnList.add(new InsnNode(Opcodes.ICONST_2)); insnList.add(new InsnNode(Opcodes.IADD)); insnList.add(new InsnNode(Opcodes.IRETURN)); ASM / BCEL Javassist cglib Byte Buddy visitorAPItreeAPI
  11. 11. • Byte code-level API gives full freedom • Requires knowledge of byte code (stack metaphor, JVM type system) • Requires a lot of manual work (stack sizes / stack map frames) • Byte code-level APIs are not type safe (jeopardy of verifier errors, visitor call order) • Byte code itself is little expressive • Low overhead (visitor APIs) • ASM is currently more popular than BCEL (used by the OpenJDK, considered as public API) • Versioning issues for ASM (especially v3 to v4) ASM / BCEL Javassist cglib Byte Buddy
  12. 12. ASM / BCEL Javassist cglib Byte Buddy int foo() { return 1 + 2; } "int foo() {" + " return 1 + 2;" + "}" • Strings are not typed (“SQL quandary”) • Specifically: Security problems! • Makes debugging difficult (unlinked source code, exception stack traces) • Bound to Java as a language • The Javassist compiler lags behind javac • Requires special Java source code instructions for realizing cross-cutting concerns
  13. 13. class SecuredService extends Service { @Override void deleteEverything() { methodInterceptor.intercept(this, Service.class.getDeclaredMethod("deleteEverything"), new Object[0], new $MethodProxy()); } class $MethodProxy implements MethodProxy { // inner class semantics, can call super } } ASM / BCEL Javassist cglib Byte Buddy class SecuredService extends Service { @Override void deleteEverything() { if(!"ADMIN".equals(UserHolder.user)) { throw new IllegalStateException("Wrong user"); } super.deleteEverything(); } } genericdelegation interface MethodInterceptor { Object intercept(Object object, Method method, Object[] arguments, MethodProxy proxy) throws Throwable }
  14. 14. ASM / BCEL Javassist cglib Byte Buddy • Discards all available type information • JIT compiler struggles with two-way-boxing (check out JIT-watch for evidence) • Interface dependency of intercepted classes • Delegation requires explicit class initialization (breaks build-time usage / class serialization) • Subclass instrumentation only (breaks annotation APIs / class identity) • “Feature complete” / little development • Little intuitive user-API
  15. 15. ASM / BCEL Javassist cglib Byte Buddy Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(value("Hello World!")) .make() .load(getClass().getClassLoader()) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!"));
  16. 16. ASM / BCEL Javassist cglib Byte Buddy class MyInterceptor { static String intercept() { return "Hello World"; } } identifiesbestmatch Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader()) .getLoaded();
  17. 17. ASM / BCEL Javassist cglib Byte Buddy Annotations that are not visible to a class loader are ignored at runtime. Thus, Byte Buddy’s classes can be used without Byte Buddy on the class path. class MyInterceptor { static String intercept(@Origin Method m) { return "Hello World from " + m.getName(); } } Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(named("toString")) .intercept(to(MyInterceptor.class)) .make() .load(getClass().getClassLoader()) .getLoaded(); providesarguments
  18. 18. ASM / BCEL Javassist cglib Byte Buddy @Origin Method|Class<?>|String Provides caller information @SuperCall Runnable|Callable<?> Allows super method call @DefaultCall Runnable|Callable<?> Allows default method call @AllArguments T[] Provides boxed method arguments @Argument(index) T Provides argument at the given index @This T Provides caller instance @Super T Provides super method proxy
  19. 19. ASM / BCEL Javassist cglib Byte Buddy class Foo { String bar() { return "bar"; } } Foo foo = new Foo(); new ByteBuddy() .redefine(Foo.class) .method(named("bar")) .intercept(value("Hello World!")) .make() .load(Foo.class.getClassLoader(), ClassReloadingStrategy.installedAgent()); assertThat(foo.bar(), is("Hello World!")); The instrumentation API does not allow introduction of new methods. This might change with JEP-159: Enhanced Class Redefiniton.
  20. 20. class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .type(named("Foo")) .transform((builder, type, loader, module) -> builder.method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Byte Buddy: Java agents
  21. 21. class TimerAdvice { @OnMethodEnter static long enter() { return System.nanoTime(); } @OnMethodExit static void exit(@Enter long start, @Origin String method) { long duration = System.nanoTime() - start; System.out.println(method + " took " + duration); } } class Foo { String bar() { long $start = System.nanoTime(); return "bar"; } } class Foo { String bar() { long $start = System.nanoTime(); String $result = "bar"; return $result; } } class Foo { String bar() { long $start = System.nanoTime(); String $result = "bar"; long $duration = System.nanoTime() – $start; System.out.println("Foo.bar()" + " took " + $duration); return $result; } } class Foo { String bar() { return "bar"; } } Byte Buddy: adding code to a method using advice
  22. 22. class Foo { String bar() { return "bar"; } } System.out.println(new Foo().bar()); public static void agentmain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .with(RedefinitionStrategy.RETRANSFORMATION) .disableClassFormatChanges() .type(named("Foo")) .transform((builder, type, loader, module) -> builder.visit(Advice.to(TimerAdvice.class) .on(named("bar"))); ) .installOn(instrumentation); } Byte Buddy: Java runtime agents // bar // Foo.bar() took 1630
  23. 23. Build-time instrumentation: API 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!")); } } Build plugins can be applied as Java agent. Adapters allow build to agent transformation. (Agent APIs are more specific.)
  24. 24. 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>
  25. 25. 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> <artifactId>foo</artifactId> </transformation> </transformations> </configuration> </plugin>
  26. 26. Build-time instrumentation with Gradle. buildscript { repositories { jCenter() } dependencies { classpath "net.bytebuddy:byte-buddy-gradle-plugin:+" } } apply plugin: "net.bytebuddy.byte-buddy" configurations { simplePlugin } dependencies { simplePlugin "bar:foo:1.0" } byteBuddy { transformation { plugin = "pkg.SimplePlugin" classPath = configurations.simplePlugin } }
  27. 27. Reality check: Reinvent Java? “Plain old Java applications” (POJAs) Working with POJOs reduces complexity. Reducing infrastructure code as a goal Many applications are built around a central infrastructure. A lot of code does not solve domain problems but bridges between domain and infrastructure. Java agents allow to add a decentralized infrastructure at runtime. In the source code, the infrastructure is only declared.
  28. 28. Java virtual machine [stack, JIT] Dalvik virtual machine [register, JIT] Android runtime [register, AOT] Android makes things more complicated. Solution: Embed the Android SDK’s dex compiler (Apache 2.0 license). Unfortunately, only subclass instrumentation possible.
  29. 29. baseline Byte Buddy cglib Javassist Java proxy (1) 0 142 515 193 70 (2a) 0 1‘126 960 1’070 1’060 (2b) 0.002 0.002 0.003 0.011 0.008 (3a) 0 882 5’408 1‘632 683 n/a (3b) 0.004 0.004 0.004 0.021 0.025 n/a Results are measured in nanoseconds (rounded). All benchmarks run with JMH, source code: https://github.com/raphw/byte-buddy (1) Extending the Object class without any methods but with a default constructor (2a) Implementing an interface with 18 methods, method stubs (2b) Executing a method of this interface (3a) Extending a class with 18 methods, super method invocation (3b) Executing a method of this class Performance: library comparison
  30. 30. I O foo() bar() qux() Performance: delegation vs. advice foo() bar() qux() qux() intercept() -XX:MaxInlineSize=35 (auto-reduced) -XX:FreqInlineSize=325 -XX:InlineSmallCode=2000 -XX:MaxInlineLevel=9 -XX:InlineSynchronizedMethods=true -XX:ReservedCodeCacheSize=48M -XX:+PrintCodeCache -XX:+PrintCodeCacheOnCompilation
  31. 31. foo() [module A] bar() [module A] qux() [module A] qux() [module A] intercept() [module B] Module moduleA = findModule("A"), moduleB = findModule("B"); moduleA.addReads(moduleB); Java 9: instrumentation meets modules instrumentation.addReads(moduleA, moduleB);
  32. 32. Loading and leaking runtime classes boot extension system wrapper Foo Bar [wrapper] Bar [inject] public class Foo { /* package-private */ String bar() { return "foo"; } } public class Bar extends Foo { @Override /* package-private */ String bar() { return "bar"; } }
  33. 33. Caching runtime classes WeakHashMap<Class<?>, Class<?>> proxies; Foo Foo$Proxy via CL WeakHashMap<Class<?>, SoftReference<Class<?>>> Map<Class<?>, Class<?>> WeakHashMap<Class<?>, WeakReference<Class<?>>> Value references key strongly (parent class). Requires active life-cycle management. When injecting into the source class loader, this is the only meaningful solution. Proxy class is collected when there is no instance available. Proxy class is collected when the heap is filled and there is no instance available. The only proper solution would be ephemerons which are not available in the JVM. Discussed in January 2016 / OpenJDK mailing list (core-libs-dev).
  34. 34. class Foo { void bar(Object arg) { /* do something */ } } class Bar extends Foo { @Override void bar(Number arg) { /* do something */ } /* bridge */ void bar(Object arg) { this.bar((Number) arg); } } class Foo<T> { void bar(T arg) { /* do something */ } } class Bar<S extends Number> extends Foo<S> { @Override void bar(S arg) { /* do something */ } } Dealing with bridge methods class Bar$Proxy extends Bar { @Override void bar(Number arg) { super.bar(arg); } @Override void bar(Object arg) { super.bar(arg); } }
  35. 35. class Foo { public void bar() { /* do something */ } } public class Bar extends Foo { /* bridge */ public void bar() { super.bar(); } } class Foo { public void bar() { /* do something */ } } public class Bar extends Foo { } Dealing with bridge methods: visibility bridges class Qux { public final void bar() { /* do something */ } } public class Baz extends Qux { } new Baz().bar(); // works Baz.class.getMethod("bar").invoke(new Baz()); // access error
  36. 36. Generic runtime types and dealing with meta data new ByteBuddy() .subclass(parameterizedType(Bar.class, String.class).build()) .method(named("foo")) .intercept(value("bar")) .attribute(ForInstrumentedMethod.INCLUDING_RECEIVER) .make(); @interface Foo {} interface Bar<T> { @Foo void foo(@Foo this, T arg); } Byte Buddy handles meta data and generic types transparently. Not only important for “build-time” instrumentation but also for meta data APIs.
  37. 37. class $MethodProxy implements MethodProxy { @Override public Object invokeSuper(Object self, Method method, Object[] arguments) { if (method.equals($bar)) { ((Foo) self).bar((Integer) arguments[0]); return null; } else if (method.equals($qux)) { return ((Foo) self).qux((String) arguments[0]); } else { throw new IllegalStateException(); } } } Super method proxies: cglib interface Foo { void bar(int arg); String qux(String arg); }
  38. 38. class $BarMethodProxy implements Runnable { final Foo self; final int arg; // constructor omitted @Override public void run() { self.bar(arg); } } Super method proxies: cglib interface Foo { void bar(int arg); String qux(String arg); } class $QuxMethodProxy implements Callable<String> { final Foo self; final String arg; // constructor omitted @Override public String call() { return self.bar(arg); } }
  39. 39. Problems caused by “optional” types class SomeFramework { void doFrameworkStuff() { if (isFancyPluginAvailable()) { init(new OptionalPluginType()); } /* do work */ } private void init(OptionalPluginType plugin) { /* do work */ } } // causes NoClassDefFoundError SomeFramework.class.getMethods();
  40. 40. Not requiring loaded types: an reflection API alternative interface TypeDescription interface MethodDescription interface FieldDescription interface AnnotationDescription When a class file transformer is applied, a class is not yet loaded and it is therefore not possible to access loaded types. To provide an API for matchers and transformers, Byte Buddy offers an abstraction to the Java reflection API: Any reference of such a description is resolved lazily. This also allows working with optional types. The Byte Buddy agent builder offers an automatic fallback as using loaded types is more performant.
  41. 41. http://rafael.codes @rafaelcodes http://documents4j.com https://github.com/documents4j/documents4j http://bytebuddy.net https://github.com/raphw/byte-buddy
  • ssusere8d0b5

    Oct. 9, 2018
  • liuliufor

    Aug. 27, 2018
  • CNiq527

    Aug. 11, 2017
  • persiacai

    Oct. 13, 2016
  • SorinS

    Oct. 8, 2016
  • khaledmahmoud44

    Sep. 29, 2016
  • zhangya_no1

    Feb. 3, 2016
  • lepffm

    Jan. 16, 2016
  • junyao8

    Jan. 11, 2016
  • zenichiamano

    Nov. 23, 2015
  • RyanKwon1

    Nov. 10, 2015
  • izzuddinsakir

    Nov. 9, 2015
  • rachmakhan

    Nov. 6, 2015
  • viliamkasala

    Nov. 5, 2015
  • BharatAndani

    Oct. 31, 2015
  • OmarMourad1

    Oct. 26, 2015
  • freeloki

    Sep. 22, 2015
  • jchauhan

    Aug. 17, 2015
  • partha_net123

    Aug. 2, 2015
  • vumc

    Apr. 12, 2015

While Java’s strict type system is a great help for avoiding programming errors, it also takes away some of the flexibility that developers appreciate when using dynamic languages. By using runtime code generation, it is possible to bring some of this flexibility back to the Java virtual machine. For this reason, runtime code generation is widely used by many state-of-the-art Java frameworks for implementing POJO-centric APIs but it also opens the door to assembling more modular applications. This presentation offers an introduction to the complex of runtime code generation and its use on the Java platform. Furthermore, it discusses the up- and downsides of several code generation libraries such as ASM, Javassist, cglib and Byte Buddy.

Views

Total views

9,047

On Slideshare

0

From embeds

0

Number of embeds

340

Actions

Downloads

191

Shares

0

Comments

0

Likes

26

×