+ All Categories
Home > Software > Invoke dynamite in Java EE with invoke dynamic

Invoke dynamite in Java EE with invoke dynamic

Date post: 27-Aug-2014
Category:
Upload: antoine-sabot-durand
View: 719 times
Download: 0 times
Share this document with a friend
Description:
This talk expose how the JDK 7 InvokeDynamic feature could be used to replace proxies in Java EE
Popular Tags:
31
Let’s Invoke Dynamite in Java EE with InvokeDynamic Antoine Sabot-Durand Senior Software Engineer Red Hat @antoine_sd / #IndyEE http://www.revistashqiptare.com/wp-content/uploads/2013/10/prishje-me-C4.jpg
Transcript
Page 1: Invoke dynamite in Java EE with invoke dynamic

Let’s Invoke Dynamite in Java EE with

InvokeDynamic

Antoine Sabot-Durand Senior Software Engineer

Red Hat @antoine_sd / #IndyEE

http://www.revistashqiptare.com/wp-content/uploads/2013/10/prishje-me-C4.jpg

Page 2: Invoke dynamite in Java EE with invoke dynamic

Antoine Sabot-Durand

• Senior Software Engineer @Red Hat

!

• Java & OSS :

• CDI co-spec lead

• CDI community development

• Tech Lead on Agorava

!

• @antoine_sd

2

Page 3: Invoke dynamite in Java EE with invoke dynamic

My support team

Page 4: Invoke dynamite in Java EE with invoke dynamic

Agenda

• Back in time

• Proxies - the sweet poison

• The Invoke Dynamic antidote

• @Inject Demo

• To be done

• Q&A

4

Page 5: Invoke dynamite in Java EE with invoke dynamic

Disclaimer

5

Page 6: Invoke dynamite in Java EE with invoke dynamic

Disclaimer

5

I’M NOT AN INVOKEDYNAMIC, BYTECODE OR ASM EXPERT, ONLY

A USER. FOR ADVANCED QUESTION, ASK

THOSE GUYS

Page 7: Invoke dynamite in Java EE with invoke dynamic

Disclaimer

5

I’M NOT AN INVOKEDYNAMIC, BYTECODE OR ASM EXPERT, ONLY

A USER. FOR ADVANCED QUESTION, ASK

THOSE GUYS

Page 8: Invoke dynamite in Java EE with invoke dynamic

Back in time

https://www.flickr.com/photos/revolweb/3985108034

Page 9: Invoke dynamite in Java EE with invoke dynamic

public void ship (String productId, String orderId, int quantity) { try { makeConnection(); con.setAutoCommit(false); updateOrderItem(productId, orderId); updateInventory(productId, quantity); con.commit(); } catch (Exception ex) { try { con.rollback(); throw new EJBException("Transaction failed: " + ex.getMessage()); } catch (SQLException sqx) { throw new EJBException("Rollback failed: " + sqx.getMessage()); } } finally { releaseConnection(); }}

Long, long time ago…

7

Page 10: Invoke dynamite in Java EE with invoke dynamic

public void ship (String productId, String orderId, int quantity) { try { makeConnection(); con.setAutoCommit(false); updateOrderItem(productId, orderId); updateInventory(productId, quantity); con.commit(); } catch (Exception ex) { try { con.rollback(); throw new EJBException("Transaction failed: " + ex.getMessage()); } catch (SQLException sqx) { throw new EJBException("Rollback failed: " + sqx.getMessage()); } } finally { releaseConnection(); }}

Long, long time ago…

7

ALL TRANSVERSE CODE HAD TO BE

DUPLICATED EVERYWHERE

Page 11: Invoke dynamite in Java EE with invoke dynamic

Then AOP was invented

• All cross-cutting concerns was extracted in one place

• Initiated at Xerox PARC in 1996

• AspectJ is released in 2001.

• Spring is released in 2004.

• Java EE adopted it in 2006 with Java EE 5

• In Java you can do AOP with code weaving (Open JPA) or theoretically with reflexion

• But the most popular tools to do AOP are… 8

@Transactional public void ship (String productId, String orderId, int quantity) { updateOrderItem(productId, orderId); updateInventory(productId, quantity); }

Page 12: Invoke dynamite in Java EE with invoke dynamic

Proxies

https://www.flickr.com/photos/mhall209/3411159477

Page 13: Invoke dynamite in Java EE with invoke dynamic

Proxies

https://www.flickr.com/photos/hape_gera/3281625420/sizes/o/in/photostream/

Page 14: Invoke dynamite in Java EE with invoke dynamic

What’s a proxy

• At the beginning it’s a design pattern in OOP :

!

!

!

• It can be implemented in static code with an interface and a « client » class wrapping another class doing the actual work

• In Java EE implementations the proxy class is dynamically created at runtime

11

« proxy provides a surrogate or a placeholder for another object to control access to it. »

Sincerely yours, The Gang Of Four

Page 15: Invoke dynamite in Java EE with invoke dynamic

private Class<T> createProxyClass(String proxyClassName) throws Exception { ArraySet<Class<?>> specialInterfaces = new ArraySet<Class<?>>(); addAdditionalInterfaces(specialInterfaces); ClassFile proxyClassType = null; if (getBeanType().isInterface()) { proxyClassType = new ClassFile(proxyClassName, Object.class.getName()); proxyClassType.addInterface(getBeanType().getName()); } else { proxyClassType = new ClassFile(proxyClassName, getBeanType().getName()); } for (Class<?> clazz : additionalInterfaces) { proxyClassType.addInterface(clazz.getName()); } List<DeferredBytecode> initialValueBytecode = new ArrayList<DeferredBytecode>(); ClassMethod staticConstructor = proxyClassType.addMethod(AccessFlag.PUBLIC, "<clinit>", "V"); addFields(proxyClassType, initialValueBytecode); addConstructors(proxyClassType, initialValueBytecode); addMethods(proxyClassType, staticConstructor); staticConstructor.getCodeAttribute().returnInstruction(); Class<T> proxyClass = cast(ClassFileUtils.toClass(proxyClassType, classLoader, domain)); BeanLogger.LOG.createdProxyClass(proxyClass, Arrays.toString(proxyClass.getInterfaces())); return proxyClass;}

Example from Weld

12

Page 16: Invoke dynamite in Java EE with invoke dynamic

What are the issues with proxies

• Need a engine for object creation : The container proliferation

• Make a lot of boilerplate code in frameworks

• Long and weird stack traces

• Two objects when one could enough

• JIT compiler cannot optimize this runtime generated code

• Costly in CPU and memory

• And strange impact on specification…

13

Page 17: Invoke dynamite in Java EE with invoke dynamic

Proxies tautologyhttp://www.rcgroups.com/forums/attachment.php?attachmentid=4004213

Page 18: Invoke dynamite in Java EE with invoke dynamic

Meet Indy

http://commons.wikimedia.org/wiki/File:Bullwhip_and_IJ_hat.jpg

Page 19: Invoke dynamite in Java EE with invoke dynamic

InvokeDynamic the good parts

• Is a JDK built-in solution to do linking at runtime

• Introduced in Java 7 with JSR 292

• Designed to implement dynamic language on JVM (JRuby, Groovy, Golo, Nashorn)

• Better than standard reflection

• Type Safe and not « interpreted »

• Better than standard bytecode manipulation

• Nearly everything is in JDK package java.lang.invoke

• Better than proxies

• Resolve all proxies issues 16

Page 20: Invoke dynamite in Java EE with invoke dynamic

InvokeDynamic the WTF part

17

http://upload.wikimedia.org/wikipedia/commons/1/14/Rubber_Duck_(8374802487).jpg

Page 21: Invoke dynamite in Java EE with invoke dynamic

InvokeDynamic the WTF part

17

http://upload.wikimedia.org/wikipedia/commons/1/14/Rubber_Duck_(8374802487).jpg

Page 22: Invoke dynamite in Java EE with invoke dynamic

InvokeDynamic the WTF part

There’s no java instruction to

produce InvokeDynamic Bytecode

instruction.

!

So we have to do byte code

manipulation to add it

17

http://upload.wikimedia.org/wikipedia/commons/1/14/Rubber_Duck_(8374802487).jpg

Page 23: Invoke dynamite in Java EE with invoke dynamic

Indy : the usual suspects

• The InvokeDynamic instruction

• It contains a reference to the bootstrap method

• The Boostrap method which does the dynamic linking

• Called once for a given indy instruction

• Return a Callsite containing the actual code

• The CallSite Object

• Contains the handle to the method to call

• Can be be mutable (we won’t show that here)

• The MethodeHandle

• Handle to the final method18

Page 24: Invoke dynamite in Java EE with invoke dynamic

http://cache.reelz.com/assets/content/repFrame/65555/indiana.jpg

Invoke dynamic call

Bootstrap method

Callsite

MethodHandle

Page 25: Invoke dynamite in Java EE with invoke dynamic

Demo

Page 26: Invoke dynamite in Java EE with invoke dynamic

Proof by stacktrace

21

Code and Readme are here : https://github.com/antoinesd/weld-invokedynamic

Page 27: Invoke dynamite in Java EE with invoke dynamic

@ApplicationScopedpublic class SecondBean { @Inject FirstBean bean; public void doSservice() { System.out.println("Service in SecondBean calling firstBean"); bean.doSomeWork(); } @PostConstruct public void init() { System.out.println("Contructing Second Bean"); }}

SecondBean Source

22

Page 28: Invoke dynamite in Java EE with invoke dynamic

public class org/jboss/weld/test/SecondBean {!! @Ljavax/enterprise/context/ApplicationScoped;()!! Lorg/jboss/weld/test/FirstBean; bean! @Ljavax/inject/Inject;()!! public doSservice()V! L0! LINENUMBER 18 L0! GETSTATIC java/lang/System.out : Ljava/io/PrintStream;! LDC "Service in SecondBean calling firstBean"! INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V! L1! LINENUMBER 19 L1! ALOAD 0! GETFIELD org/jboss/weld/test/SecondBean.bean : Lorg/jboss/weld/test/FirstBean;! INVOKEVIRTUAL org/jboss/weld/test/FirstBean.doSomeWork ()V! L2! LINENUMBER 21 L2! RETURN!}

SecondBean standard bytecode

23

Page 29: Invoke dynamite in Java EE with invoke dynamic

public class org/jboss/weld/test/SecondBean {!! @Ljavax/enterprise/context/ApplicationScoped;()!! Lorg/jboss/weld/test/FirstBean; bean! @Ljavax/inject/Inject;()!! public doSservice()V! L0! LINENUMBER 18 L0! GETSTATIC java/lang/System.out : Ljava/io/PrintStream;! LDC "Service in SecondBean calling firstBean"! INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V! L1! LINENUMBER 19 L1! ALOAD 0! INVOKEDYNAMIC bean(Lorg/jboss/weld/test/SecondBean;)Lorg/jboss/weld/test/FirstBean; [! // handle kind 0x6 : INVOKESTATIC! org/jboss/weld/invokedynamic/Bootstraper.bootstrapGetBean(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite;! // arguments:! "bean"! ]! INVOKEDYNAMIC doSomeWork(Lorg/jboss/weld/test/FirstBean;)V [! // handle kind 0x6 : INVOKESTATIC! org/jboss/weld/invokedynamic/Bootstraper.bootstrapCallBeanMethod(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;! // arguments:! // handle kind 0x5 : INVOKEVIRTUAL! org/jboss/weld/test/FirstBean.doSomeWork()V, ! "bean"! ]! L2! LINENUMBER 21 L2! RETURN!}

SecondBean Indy bytecode

24

Page 30: Invoke dynamite in Java EE with invoke dynamic

To be done…

• Implement @Inject on constructor and setter

• Manage the use case of field containing bean without Injection Point

• Add Indy to Instance<> methods

• Implement interceptors

• Implement decorators

• Remove all proxies from Weld

25

Page 31: Invoke dynamite in Java EE with invoke dynamic

Q&A


Recommended