JDK 7 출시 기념 (2011.7)JDK 7 소개 #5 invokedynamic<br />김용환<br />knight76.tistory.com<br />Knight76 at gmail.com<br />1<br />
좋은 레퍼런스<br />http://java.sun.com/developer/technicalArticles/DynTypeLang/index.html<br />http://androidkr.blogspot.com/201...
For Who<br />JAVA 1.6부터 다른 언어를 지원 (Rhino)<br />정적 타입 언어 (非 자바)를 jvm에서 안정적이고, 빨리 실행시켜줄 수 있도록 지원 요청<br />
Java language / JVM<br />Java language 는 JVM과 다르다.<br />특징<br />Java compiler<br />사람이 write한 java code를 JVM에서 실행가능하도록byte...
기존 사례<br />Groovy 코드 -> class로 컴파일  -> JVM실행<br />JRuby코드 -> class로컴파일   (spring의 JRubyScriptUtils.createJRubyObject메소드) -...
둘의장점을 이용<br />Ruby/Python<br />(Dynamic Language)<br />JVM 특징<br />(고성능, 재활용, <br />JIT, GC, <br />다양한 OS 지원)<br />
But, 이슈<br />동적언어와 정적 언어 특징<br />정적 타입 언어(java)는Compile 레벨에서 Type Checking이 엄격하게 이루어짐<br />동적 타입 언어(dynamic type)는 Type Ch...
JVM 이슈 : 메소드<br />JVM 이슈 : 메소드<br />동적언어에서는메소드의파라미터 타입을 굳이 알 수 않아도 되지만, JVM은 byte code 명령어들을 이용하기 위해서 method, method안의 클래스...
구현<br />타입 정보가 없으면, reflection API를이용해서 java.lang.reflect.Method 클래스를 생성하고, Method 클래스의 invoke 메소드로 호출하는 형태(Proxy)<br />Re...
빠른 속도<br />Reflection API를 쓰지 않아도 바로 invoke 해 줄 수있고, 속도도 빠른 새로운 API가 필요<br />JVM 의 invoke 명령어 중 새로운 API를 추가하자!<br />
잠깐.. JVM byte code 공부<br />
JVM byte code<br />JVM에서 동작하는 native language (assembly와 비슷)<br />JVM byte code<br />Stack에 작업(push/pop/dup/swap)을 하고, 실행시...
JVM byte code의 instruction<br />ldc/const : stack에 값을 push <br />load/store : 로컬 변수 접근 관련<br />aaload/*aload : array로부터 값을...
Java ByteCode출력방법<br />javap –c 클래스이름<br />
예제<br />String s = "Hello World";<br />System.out.println(s);<br />java<br />ldc #2          // ‘Hello World’ stack에 저장(pu...
JVM invokevirtualinstuction이슈<br />invokevirtual instruction은 메소드의파라미터의 클래스타입(descriptor)을 반드시 알아야 함<br />invokevirtual <m...
JVM invokevirtualinstuction예제<br />Object x; <br />... <br />x.equals("hello"); <br />java<br />aload_1 ; 로컬 변수 ‘x’를 스택첫번째...
invokestatic<br />
invokestatic<br />String s = System.getProperty("java.home");<br />java<br />ldc#2              //String ”java.home”을 stac...
invokestatic<br />
invokestatic<br />
invokevirtual<br />
invokevirtual<br />PrintStream out = System.out;<br />out.println("Hello World");<br />java<br />getstatic #16<br />astore...
invokevirtual<br />출처 : http://cr.openjdk.java.net/~jrose/pres/200906-Cookbook.pdf<br />
invokevirtual<br />
invokevirtual<br />
invokedynamic<br />
invokedynamic<br />function max(x, y) {<br />    if (x.lessThan(y)) then y else x<br />}<br />동적<br />타입<br />언어<br />aloa...
invokedynamic<br />C언어의 함수 포인터와 비슷!<br />
invokedynamic이후Bootstrap instruction 부트 로직<br />
JVM 동작 순서<br />invokedynamic명령어를 실행하기 전에 java.lang.invoke.CallSite를 확인<br />CallSite가 없다면, 동적 타입 언어의 런타임에서 bootstrap 메소드를 ...
up call<br />리눅스<br />low level 이 high level에 있는 함수를 호출하는 것이죠. signal handler 같은 것<br />JVM<br />JVM의 invokedynamic이 boots...
코드 구현 예제 #1<br />public class HelloWorld {<br />    public static void main(String[] args) {<br />//PSEUDOCODE FOR A JVM I...
코드 구현 예제 #2<br />public class IntegerOps {<br />public static Integer adder(Integer x, Integer y) {<br />    return x + y;...
코드 구현 예제 #2<br />InvokeVirtual과 달리 메소드 호출을 위한 클래스 정보가 필요 없다. 대신 길다.<br />Jvmbytecode<br />invokedynamicinvokedynamic<br />...
코드 구현 예제 #2<br />invokedynamicinvokedynamic<br />REF_invokestatic:<br />Example.mybsm:<br />      "(Ljava/lang/invoke/Meth...
API<br />java.lang.invoke..MethodHandle (MH) <br />JVM 메소드에 대한 anonymous reference 을 가지고 있음<br />MethodHandles.Lookup<br /...
JSR 292<br />JSR292<br />
JSR 292 -Spec.zip<br />
JSR 292<br />JRuby팀과협업<br />enhanced bytecode + a new API<br />invokedynamic<br />java.lang.invoke<br />MethodHandle(일종의 함...
JVM Spec Changed<br />
참고<br />
JRuby실전 테스트<br />jruby에서 jvm버전을 변경하고 싶을 때는 JAVA_HOME을 변경하면 된다.  (따로 properties 설정은 없다.)<br />C:jruby-1.6.3-without-jvmbin>...
JRuby실전 테스트<br />myruby.rb<br />def max(a,b)<br />  if a < b<br />    b<br />  else<br />    a<br />  end<br />end<br />de...
JRuby실전 테스트<br />a.JRubyExample.java<br />public static void main(String[] args) throws Exception {<br />ScriptEnginejruby...
JRuby실전 테스트<br />C:jruby-1.6.3-without-jvmbin>jrubyc.bat myruby.rb<br />  public static org.jruby.runtime.builtin.IRubyObj...
JRuby의 성능<br />http://eyweb-images.s3.amazonaws.com/blog_crossimp.jpg<br />
정리<br />Jruby<br />1.6.3까지는 invokedynamic사용하지 않음. (invokedynamic테스트 버전은 따로 있음.)<br />대신 내부적으로 invokedynamic비슷한 구현을 이미 하고 있...
To be continued #6<br />49<br />
Upcoming SlideShare
Loading in...5
×

Jdk(java) 7 - 5. invoke-dynamic

3,900

Published on

Published in: Technology, News & Politics
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,900
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Jdk(java) 7 - 5. invoke-dynamic

  1. 1. JDK 7 출시 기념 (2011.7)JDK 7 소개 #5 invokedynamic<br />김용환<br />knight76.tistory.com<br />Knight76 at gmail.com<br />1<br />
  2. 2. 좋은 레퍼런스<br />http://java.sun.com/developer/technicalArticles/DynTypeLang/index.html<br />http://androidkr.blogspot.com/2010_07_01_archive.html<br />http://cr.openjdk.java.net/~jrose/pres/200906-Cookbook.pdf<br />http://download.oracle.com/javase/7/docs/technotes/guides/vm/multiple-language-support.html<br />Jsr문서<br />dynamically_typed_lang-jdk7-final-oth-JSpecindex.html<br />
  3. 3. For Who<br />JAVA 1.6부터 다른 언어를 지원 (Rhino)<br />정적 타입 언어 (非 자바)를 jvm에서 안정적이고, 빨리 실행시켜줄 수 있도록 지원 요청<br />
  4. 4. Java language / JVM<br />Java language 는 JVM과 다르다.<br />특징<br />Java compiler<br />사람이 write한 java code를 JVM에서 실행가능하도록byte 코드를 생성<br />HelloWorld.java -> HellowWorld.class<br />Java Virtual Machine<br /> byte코드와 class 파일 포맷을 가지고 실행<br />HellowWorld.class -> 실행<br />이슈<br />Java language 이슈가 아닌…<br />정적 타입 언어를 바로 JVM 상에서 돌아가는 것 자체가 어려움 (interoperability)<br />JVM (java virtual machine)의 실행 속도 이슈! (performance)<br />
  5. 5. 기존 사례<br />Groovy 코드 -> class로 컴파일 -> JVM실행<br />JRuby코드 -> class로컴파일 (spring의 JRubyScriptUtils.createJRubyObject메소드) -> JVM 실행<br />단점<br />JVM에서 돌아갈 수 있도록 작업을 많이 해야 했음. JVM dependent code가 많았음<br />
  6. 6. 둘의장점을 이용<br />Ruby/Python<br />(Dynamic Language)<br />JVM 특징<br />(고성능, 재활용, <br />JIT, GC, <br />다양한 OS 지원)<br />
  7. 7. But, 이슈<br />동적언어와 정적 언어 특징<br />정적 타입 언어(java)는Compile 레벨에서 Type Checking이 엄격하게 이루어짐<br />동적 타입 언어(dynamic type)는 Type Checking이 Runtime때 실행. 변수는 어떤 타입이든지 상관없음 (javascript, ruby, python..)<br />
  8. 8. JVM 이슈 : 메소드<br />JVM 이슈 : 메소드<br />동적언어에서는메소드의파라미터 타입을 굳이 알 수 않아도 되지만, JVM은 byte code 명령어들을 이용하기 위해서 method, method안의 클래스 타입, descriptor 형식이 필요<br /> function max (x,y) {<br /> if x.lessThan(y) then y else x<br /> } <br />동적언어메소드파라미터의 타입정보가 없는 메소드<br />
  9. 9. 구현<br />타입 정보가 없으면, reflection API를이용해서 java.lang.reflect.Method 클래스를 생성하고, Method 클래스의 invoke 메소드로 호출하는 형태(Proxy)<br />Reflection 호출 자체가 실행속도에 안좋은 영향을 줌. 성능 저하<br />예) Spring에서는 Proxy 개선 : CGLIB Proxy <br />Reflection 없이 속도 향상!<br />
  10. 10. 빠른 속도<br />Reflection API를 쓰지 않아도 바로 invoke 해 줄 수있고, 속도도 빠른 새로운 API가 필요<br />JVM 의 invoke 명령어 중 새로운 API를 추가하자!<br />
  11. 11. 잠깐.. JVM byte code 공부<br />
  12. 12. JVM byte code<br />JVM에서 동작하는 native language (assembly와 비슷)<br />JVM byte code<br />Stack에 작업(push/pop/dup/swap)을 하고, 실행시키는 machanism<br />Operand stack : byte code가 실행할 수 있는 임시용의 stack (cpu의 register stack)<br />
  13. 13. JVM byte code의 instruction<br />ldc/const : stack에 값을 push <br />load/store : 로컬 변수 접근 관련<br />aaload/*aload : array로부터 값을 얻기<br />iinc : i++<br />if_icmpge :conditional jump<br />return<br />Invoke <br />virtual : 인터페이스가 아닌 메소드를 호출. (대부분)<br />interface : 인터페이스 메소드를 호출<br />static : static 호출<br />special : 생성자와super class 메소드의 구현 메소드를 호출<br />
  14. 14. Java ByteCode출력방법<br />javap –c 클래스이름<br />
  15. 15. 예제<br />String s = "Hello World";<br />System.out.println(s);<br />java<br />ldc #2 // ‘Hello World’ stack에 저장(push)한다.<br />astore_1 //Stack에서 ‘Hellow World’를 꺼내 로컬변수 1에 저장한다.<br />getstatic#3 //System.out에서 static field인 PrintStream클래스를 꺼낸다.<br />aload_1 // 로컬변수 1에서 가르키는Stirng을 읽는다.<br />invokevirtual #4 // PrintStream의 println을 호출한다. <br />// java/io/PrintStream.println:(Ljava/lang/String;)V<br />jvm<br />
  16. 16. JVM invokevirtualinstuction이슈<br />invokevirtual instruction은 메소드의파라미터의 클래스타입(descriptor)을 반드시 알아야 함<br />invokevirtual <method-spec><br />classname, methodname,descriptor<br />com/google/Myclass/myMethod(Ljava/lang/String;)V<br />----------------------- ---------------------<br /> ------------- <br />descriptor<br />classname<br />methodname<br />
  17. 17. JVM invokevirtualinstuction예제<br />Object x; <br />... <br />x.equals("hello"); <br />java<br />aload_1 ; 로컬 변수 ‘x’를 스택첫번째에 저장<br />ldc"hello" ; 스택에‘hello’라는 Sting값을 저장<br />; ‘equals’ 메소드 호출<br />; 스택에 저장되는 값은 Boolgean값(Z)<br />invokevirtual java/lang/Object/equals(Ljava/lang/Object;)Z<br />jvm<br />
  18. 18. invokestatic<br />
  19. 19. invokestatic<br />String s = System.getProperty("java.home");<br />java<br />ldc#2 //String ”java.home”을 stack에 저장<br />invokestatic#3 //Method java/lang/System.getProperty:<br /> // (Ljava/lang/String;)Ljava/lang/String;<br />astore_1<br />jvm<br />
  20. 20. invokestatic<br />
  21. 21. invokestatic<br />
  22. 22. invokevirtual<br />
  23. 23. invokevirtual<br />PrintStream out = System.out;<br />out.println("Hello World");<br />java<br />getstatic #16<br />astore_1<br />aload_1<br />ldc#2<br />invokevirtual #4 //Method java/io/PrintStream.println:<br /> //(Ljava/lang/String;)V<br />jvm<br />
  24. 24. invokevirtual<br />출처 : http://cr.openjdk.java.net/~jrose/pres/200906-Cookbook.pdf<br />
  25. 25. invokevirtual<br />
  26. 26. invokevirtual<br />
  27. 27. invokedynamic<br />
  28. 28. invokedynamic<br />function max(x, y) {<br /> if (x.lessThan(y)) then y else x<br />}<br />동적<br />타입<br />언어<br />aload_1; aload_2<br />invokedynamic#3 // NameAndTypelessThan:<br /> // (Ljava/lang/Object;Ljava/lang/Object;)Z<br />if_icmpeq<br />jvm<br />Boolean 리턴타입. Argument는 타입없는object<br />
  29. 29. invokedynamic<br />C언어의 함수 포인터와 비슷!<br />
  30. 30. invokedynamic이후Bootstrap instruction 부트 로직<br />
  31. 31. JVM 동작 순서<br />invokedynamic명령어를 실행하기 전에 java.lang.invoke.CallSite를 확인<br />CallSite가 없다면, 동적 타입 언어의 런타임에서 bootstrap 메소드를 호출<br />Bootstrap 메소드는CallSite객체를 반환(invokedynamic은 CallSite에 링크됨)<br />invokedynamic은 CallSite에 저장된 java.net.MethodHandle(MH)를 이용해서 메소드 호출<br />CallSite가 이미 등록된 invokedynamic이 다시 실행되면, 위 과정 없이 바로 메소드 호출(invokedynamic이 구현에 대한 MethodHandle을 한번이라도 사용하면, 그 MethodHandle을 사용)<br />
  32. 32. up call<br />리눅스<br />low level 이 high level에 있는 함수를 호출하는 것이죠. signal handler 같은 것<br />JVM<br />JVM의 invokedynamic이 bootstrap 메소드를 호출하는 것<br />
  33. 33. 코드 구현 예제 #1<br />public class HelloWorld {<br /> public static void main(String[] args) {<br />//PSEUDOCODE FOR A JVM INSTRUCTION<br /> //invokedynamic[#bootstrapDynamic]("Hello World", 2, 3.14);<br /> }<br /> private static void printArgs(Object... args) {<br />System.out.println(java.util.Arrays.deepToString(args));<br /> }<br /> private static MethodHandleprintArgs;<br /> static {<br />MethodHandles.Lookuplookup = MethodHandles.lookup();<br /> Class thisClass = lookup.lookupClass(); <br />try {<br />printArgs= lookup.findStatic(thisClass, "printArgs", MethodType.methodType(void.class, <br /> Object[].class));<br />} catch (Exception e) {<br />e.printStackTrace();<br />}<br /> }<br />private staticCallSitebootstrapDynamic(MethodHandles.Lookup caller, String name, <br />MethodType type) {<br />return new ConstantCallSite(printArgs.asType(type));<br /> }<br />}<br />
  34. 34. 코드 구현 예제 #2<br />public class IntegerOps {<br />public static Integer adder(Integer x, Integer y) {<br /> return x + y;<br /> }<br />}<br />public class Example {<br /> public static CallSitemybsm(MethodHandles.LookupcallerClass, String dynMethodName, MethodTypedynMethodType) throws Throwable {<br />MethodHandlemh= callerClass.findStatic(Example.class, "IntegerOps.adder", <br />MethodType.methodType(Integer.class, Integer.class, Integer.class));<br /> if (!dynMethodType.equals(mh.type())) {<br />mh = mh.asType(dynMethodType);<br /> }<br /> return new ConstantCallSite(mh);<br /> }<br />}<br />
  35. 35. 코드 구현 예제 #2<br />InvokeVirtual과 달리 메소드 호출을 위한 클래스 정보가 필요 없다. 대신 길다.<br />Jvmbytecode<br />invokedynamicinvokedynamic<br />REF_invokestatic:<br />Example.mybsm:<br /> "(Ljava/lang/invoke/MethodHandles/Lookup;<br />Ljava/lang/String;<br />Ljava/lang/invoke/MethodType;)<br />Ljava/lang/invoke/CallSite;":<br /> +:<br /> "(Ljava/lang/Integer;<br />Ljava/lang/Integer;)<br />Ljava/lang/Integer;";<br />
  36. 36. 코드 구현 예제 #2<br />invokedynamicinvokedynamic<br />REF_invokestatic:<br />Example.mybsm:<br /> "(Ljava/lang/invoke/MethodHandles/Lookup;<br />Ljava/lang/String;<br />Ljava/lang/invoke/MethodType;)<br />Ljava/lang/invoke/CallSite;":<br /> +:<br /> "(Ljava/lang/Integer;<br />Ljava/lang/Integer;)<br />Ljava/lang/Integer;";<br />bootstrap 메소드가addr static 메소드를 호출<br />1<br />2<br />Bootstrap의 Full Qualified name인 Example.mybsm<br />3<br />bootstrap 메소드가addr static 메소드를 호출<br />
  37. 37. API<br />java.lang.invoke..MethodHandle (MH) <br />JVM 메소드에 대한 anonymous reference 을 가지고 있음<br />MethodHandles.Lookup<br />factory for creating method handles<br />java.lang.invoke.CallSite<br />MethodHandler변수를 가지고 있는 Holder<br />ConstantCallSite, MutableCallSite<br />BootstrapMethodError<br />invokedynamic호출후bootstrap 메소드을못찾거나Call site을 리턴하지 못하면 에러 발생<br />
  38. 38. JSR 292<br />JSR292<br />
  39. 39. JSR 292 -Spec.zip<br />
  40. 40. JSR 292<br />JRuby팀과협업<br />enhanced bytecode + a new API<br />invokedynamic<br />java.lang.invoke<br />MethodHandle(일종의 함수 포인터)<br />Combinators<br />provide adhoc classes: ClassValue(캐쉬), SwitchPoint (상태확인)<br />
  41. 41. JVM Spec Changed<br />
  42. 42. 참고<br />
  43. 43. JRuby실전 테스트<br />jruby에서 jvm버전을 변경하고 싶을 때는 JAVA_HOME을 변경하면 된다. (따로 properties 설정은 없다.)<br />C:jruby-1.6.3-without-jvmbin>jruby.exe -v<br />jruby 1.6.3 (ruby-1.8.7-p330) (2011-07-07 965162f) (Java HotSpot(TM) Client VM 1.7.0) [Windows 7-x86-java]<br />C:jruby-1.6.3-without-jvmbin>java -classpath.;jruby.jar a.JRubyExample<br />num: 6<br />C:jruby-1.6.3-without-jvmbin><br />
  44. 44. JRuby실전 테스트<br />myruby.rb<br />def max(a,b)<br /> if a < b<br /> b<br /> else<br /> a<br /> end<br />end<br />defgetMax(number1, number2)<br /> f = max(number1, number2)<br /> return f<br />end<br />
  45. 45. JRuby실전 테스트<br />a.JRubyExample.java<br />public static void main(String[] args) throws Exception {<br />ScriptEnginejruby = new ScriptEngineManager().getEngineByName("jruby");<br />jruby.eval(new BufferedReader(new FileReader("myruby.rb")));<br />jruby.put("number1", 6);<br />jruby.put("number2", 9);<br /> long num = (Long) jruby.eval("getMax($number1, $number1)");<br />System.out.println("num: " + num);<br />}<br />
  46. 46. JRuby실전 테스트<br />C:jruby-1.6.3-without-jvmbin>jrubyc.bat myruby.rb<br /> public static org.jruby.runtime.builtin.IRubyObject method__0$RUBY$max(myruby,<br />org.jruby.runtime.ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jru<br />by.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject, org.jruby<br />.runtime.Block);<br /> Code:<br /> 0: aload_3<br /> 1: astore 10<br /> 3: aload 4<br /> 5: astore 11<br /> 7: aload_0<br /> 8: invokevirtual #33 // Method getCallSite0:()Lorg/jruby/<br />runtime/CallSite;<br /> 11: aload_1<br /> 12: aload_2<br /> 13: aload 10<br /> 15: aload 11<br /> 17: invokevirtual #39 // Method org/jruby/runtime/CallSite<br />.call:(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;L<br />org/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;)Lo<br />rg/jruby/runtime/builtin/IRubyObject;<br /> 20: invokeinterface #45, 1 // InterfaceMethod org/jruby/runtime<br />/builtin/IRubyObject.isTrue:()Z<br /> 25: ifeq 33<br /> 28: aload 11<br /> 30: goto 35<br /> 33: aload 10<br /> 35: areturn<br />비슷한 구현이 이미 되어 있음<br />
  47. 47. JRuby의 성능<br />http://eyweb-images.s3.amazonaws.com/blog_crossimp.jpg<br />
  48. 48. 정리<br />Jruby<br />1.6.3까지는 invokedynamic사용하지 않음. (invokedynamic테스트 버전은 따로 있음.)<br />대신 내부적으로 invokedynamic비슷한 구현을 이미 하고 있음 <br />Groovy<br />Jruby처럼 내부적으로는 invokedynamic비슷한 구현 함<br />앞으로 많은 언어들이 쓸 수 있도록 배려했고, 비슷하게 구현한 것들은 조금 더 빠른 속도가 날 수 있으며, 더 많은 언어들이 이 기능을 사용할 수 있음<br />
  49. 49. To be continued #6<br />49<br />

×