ÔÚJava
7µÄ·¢²¼°æÖаüº¬Á˶àÏîеÄÌØÐÔ£¬ÕâÐ©ÌØÐÔÕ§¿´ÉÏÈ¥Java¿ª·¢ÈËÔ±¶ÔËüÃǵÄʹÓ÷dz£ÓÐÏÞ£¬ÔÚÎÒÃÇ֮ǰµÄÎÄÕÂÖУ¬Ôø¾¶ÔÆä½øÐйý½éÉÜ¡£
µ«ÊÇ£¬ÆäÖÐÓÐÏîÌØÐÔ¶ÔÓÚʵÏÖJava 8ÖС°Í·°æ±êÌ⡱ÀàÐ͵ÄÌØÐÔÀ´ËµÖÁ¹ØÖØÒª£¨ÈçlambdasºÍĬÈÏ·½·¨£©¡£ÔÚ±¾ÎÄÖУ¬ÎÒÃǽ«»áÉîÈëѧϰinvokedynamic£¬²¢²ûÊöËü¶ÔÓÚJavaƽ̨ÒÔ¼°ÏñJRubyºÍNashornÕâÑùµÄJVMÓïÑÔÀ´½²ÎªºÎÈç´ËÖØÒª¡£
invokedynamic×î³õµÄ¹¤×÷ÖÁÉÙʼÓÚ2007Ä꣬¶øµÚÒ»´Î³É¹¦µÄ¶¯Ì¬µ÷Ó÷¢ÉúÔÚ2008Äê8ÔÂ26ÈÕ¡£Õâ±ÈOracleÊÕ¹ºSun»¹ÒªÔ磬°´ÕÕ´ó¶àÊý¿ª·¢ÈËÔ±µÄ±ê×¼£¬Õâ¸öÌØÐÔµÄÑз¢ÒѾ³ÖÐøÁËÏ൱³¤µÄʱ¼ä¡£
Ïà¹Ø³§ÉÌÄÚÈÝ
¼Ü¹¹Ê¦Ó¦¸Ã°ÑÎÕÕâЩ¼¼ÊõÇ÷ÊÆ100¸öÐÞÁ¶³É¼¼Êõ´ó¿§µÄÃû¶î£¬¾ÍµÈÄãÀ´£¡¡°ÎåÔÆ³öá¶£¬Ë½È˶©ÖÆ¡±UCloud
UCan¼¼ÊõÖ®Ò¹£¬µÈÄãÀ´Ô¼µÎµÎ³öÐÐiOS¶ËÊÝÉíʵ¼ùÁÄÍê´óÊý¾Ý¸ÅÄÎÒÃÇÔÙÀ´Ì¸Ì¸´óÊý¾ÝÓ¦ÓÃ
ÖµµÃ×¢ÒâµÄÊÇ£¬´ÓJava 1.0µ½ÏÖÔÚ£¬invokedynamicÊǵÚÒ»¸öмÓÈëµÄJava×Ö½ÚÂ룬ËüÓëÒÑÓеÄ×Ö½ÚÂëinvokevirtual¡¢invokestatic¡¢invokeinterfaceºÍinvokespecial×éºÏÔÚÁËÒ»Æð¡£ÒÑÓеÄÕâËĸö²Ù×÷ÂëʵÏÖÁËJava¿ª·¢ÈËÔ±ËùÊìÖªµÄËùÓÐÐÎʽµÄ·½·¨·ÖÅÉ£¨dispatch£©£º
1.invokevirtual¡ª¡ª¶ÔʵÀý·½·¨µÄ±ê×¼·ÖÅÉ
2.invokestatic¡ª¡ªÓÃÓÚ·ÖÅɾ²Ì¬·½·¨
3.invokeinterface¡ª¡ªÓÃÓÚͨ¹ý½Ó¿Ú½øÐз½·¨µ÷ÓõķÖÅÉ
4.invokespecial¡ª¡ªµ±ÐèÒª½øÐзÇÐ飨Ҳ¾ÍÊÇ¡°¾«È·¡±£©·ÖÅÉʱ»áÓõ½
ÓÐЩ¿ª·¢ÈËÔ±¿ÉÄÜ»áºÃÆæÆ½Ì¨ÎªºÎÐèÒªÕâËÄÖÖ²Ù×÷Â룬ËùÒÔÎÒÃÇ¿´Ò»¸ö¼òµ¥µÄÑùÀý£¬Õâ¸öÑùÀý»áÓõ½²»Í¬µÄµ÷ÓòÙ×÷Â룬ÒÔ´ËÀ´²ûÊöËüÃÇÖ®¼äµÄ²îÒ죺
public class InvokeExamples { public static void main(String[] args) { InvokeExamples sc = new InvokeExamples(); sc.run(); }
private void run() {
List ls = new ArrayList();
ls.add("Good Day");
ArrayList als = new ArrayList();
als.add("Dydh Da");
}
} |
ÎÒÃÇ¿ÉÒÔʹÓÃjavap·´»ã±à´Ó¶øµÃµ½ËüËù²úÉúµÄ×Ö½ÚÂ룺
javap -c InvokeExamples.class
public class kathik.InvokeExamples {
public kathik.InvokeExamples();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class kathik/InvokeExamples
3: dup
4: invokespecial #3 // Method "":()V
7: astore_1
8: aload_1
9: invokespecial #4 // Method run:()V
12: return
private void run();
Code:
0: new #5 // class java/util/ArrayList
3: dup
4: invokespecial #6 // Method java/util/ArrayList."":()V
7: astore_1
8: aload_1
9: ldc #7 // String Good Day
11: invokeinterface #8, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: new #5 // class java/util/ArrayList
20: dup
21: invokespecial #6 // Method java/util/ArrayList."":()V
24: astore_2
25: aload_2
26: ldc #9 // String Dydh Da
28: invokevirtual #10 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
31: pop
32: return
} |
ÔÚÕâ¸öʾÀýÖУ¬Õ¹ÏÖÁËËĸöµ÷ÓòÙ×÷ÂëÖеÄÈý¸ö£¨Ê£ÏµÄÒ»¸öÒ²¾ÍÊÇinvokestatic£¬ÊÇÒ»¸ö·Ç³£¼òµ¥µÄÀ©Õ¹£©¡£×÷Ϊ¿ªÊ¼£¬ÎÒÃÇ¿ÉÒÔ¿´Ò»ÏÂÈçϵÄÁ½¸öµ÷Óã¨ÔÚrun·½·¨µÄ×Ö½Ú11ºÍ28£©£º
ls.add("Good Day")
ºÍ
als.add("Dydh Da")
ÔÚJavaÔ´ÂëÖÐËüÃÇ¿´ÆðÀ´·Ç³£ÏàËÆ£¬µ«ËüÃÇʵ¼ÊÉÏÈ´´ú±íÁ½ÖÖ²»Í¬µÄ×Ö½ÚÂë¡£
¶ÔÓÚjavacÀ´Ëµ£¬±äÁ¿ls¾ßÓеľ²Ì¬ÀàÐÍÊÇList<String>£¬¶øListÊÇÒ»¸ö½Ó¿Ú¡£ËùÒÔ£¬ÔÚÔËÐÐʱ·½·¨±í£¨Í¨³£³ÆÎª¡°vtable¡±£©ÖУ¬add()·½·¨µÄ¾«È·Î»Öû¹Ã»ÓÐÔÚ±àÒëʱȷ¶¨¡£Òò´Ë£¬Ô´Âë±àÒëÆ÷»áÉú³ÉÒ»¸öinvokeinterfaceÖ¸Á½«Êµ¼ÊµÄ·½·¨²éÕÒÍÆ³Ùµ½ÔËÐÐÆÚ£¬Ò²¾ÍÊǵ±lsµÄʵ¼ÊvtableÄܹ»Ì½²éµ½²¢ÇÒadd()·½·¨µÄλÖÃÄܹ»ÕÒµ½µÄʱºò¡£
ÓëÖ®Ïà·´£¬¶Ôals.add("Dydh Da")µÄµ÷ÓÃÊÇͨ¹ýalsÀ´Ö´Ðеģ¬ÕâÀïµÄ¾²Ì¬ÀàÐÍÊÇÀàÀàÐÍ£¨class
type£©¡ª¡ªArrayList<String>¡£ÕâÒâζ×ÅÔÚvtableÖУ¬·½·¨µÄλÖÃÔÚ±àÒëÆÚÊÇ¿ÉÖªµÄ¡£Òò´Ë£¬javac»áÕë¶ÔÕâ¸ö¾«È·µÄvtableÌõÄ¿Éú³ÉÒ»¸öinvokevirtualÖ¸Áî¡£²»¹ý£¬×îÖյķ½·¨Ñ¡ÔñÒÀÈ»ÊÇÔÚÔËÐÐÆÚÈ·¶¨µÄ£¬ÒòΪÕâÀﻹÓз½·¨ÖØÐ´£¨overriding£©µÄ¿ÉÄÜÐÔ£¬µ«ÊÇvtable
slotÔÚ±àÒëÆÚ¾ÍÒѾȷ¶¨ÁË¡£
³ý´ËÖ®Í⣬Õâ¸öÑùÀý»¹Õ¹ÏÖÁËinvokespecialµÄÁ½¸öʹÓó¡¾°¡£Õâ¸ö²Ù×÷ÂëÓÃÓÚÔÚÔËÐÐʱȷ¶¨ÈçºÎ·ÖÅɵij¡¾°Ö®ÖУ¬¾ßÌåÀ´½²£¬ÔÚÕâÀïûÓз½·¨ÖØÐ´µÄÐèÇó£¬ÁíÍâÕâÒ²²»¿ÉÄÜʵÏÖ¡£ÑùÀýÖÐËù²ûÊöµÄ³¡¾°ÊÇprivate
methodsºÍsuper calls£¬ÕâЩ·½·¨ÔÚ±àÒëÆÚÊÇ¿ÉÖªµÄ£¬²¢ÇÒÎÞ·¨½øÐÐÖØÐ´¡£
ϸÐĵĶÁÕß¿ÉÄÜÒѾ·¢ÏÖ£¬¶ÔJava·½·¨µÄËùÓе÷Óö¼±àÒë³ÉÁËËĸö²Ù×÷ÂëÖеÄijһ¸ö£¬ÄÇôÎÊÌâ¾ÍÀ´ÁË¡ª¡ªinvokedynamicÊÇ×öʲôµÄ£¬Ëü¶ÔÓÚJava¿ª·¢ÈËÔ±ÓÐʲôÓô¦ÄØ£¿
Õâ¸öÌØÐÔµÄÖ÷ҪĿ±êÔÚÓÚ´´½¨Ò»¸ö×Ö½ÚÂ룬ÓÃÓÚ´¦ÀíÐÂÐ͵ķ½·¨·ÖÅÉ¡ª¡ªËüµÄ±¾ÖÊÊÇÔÊÐíÓ¦Óü¶±ðµÄ´úÂëÀ´È·¶¨Ö´ÐÐÄÄÒ»¸ö·½·¨µ÷Óã¬Ö»ÓÐÔÚµ÷ÓÃÒªÖ´ÐеÄʱºò£¬²Å»á½øÐÐÕâÖÖÅжϡ£ÕâÑùµÄ»°£¬Ïà¶ÔÓÚJavaƽ̨֮ǰËùÌṩµÄ±à³Ì·ç¸ñ£¬ÔÊÐíÓïÑԺͿò¼ÜµÄ±àдÈËÔ±Ö§³Ö¸ü¼Ó¶¯Ì¬µÄ±àÂë·ç¸ñ¡£
ËüµÄÄ¿µÄÔÚÓÚÓÉÓû§´úÂëͨ¹ý·½·¨¾ä±úAPI£¨method handles API£©ÔÚÔËÐÐʱȷ¶¨ÈçºÎ·ÖÅÉ£¬Í¬Ê±±ÜÃâ·´Éä´øÀ´µÄÐÔÄܳͷ£ºÍ°²È«ÎÊÌ⡣ʵ¼ÊÉÏ£¬invokedynamicËùÐû³ÆµÄÄ¿±ê¾ÍÊÇÒ»µ©¸ÃÌØÐÔ×ã¹»³ÉÊ죬ËüµÄËÙ¶ÈÒªÏñ³£¹æµÄ·½·¨·ÖÅÉ£¨invokevirtual£©Ò»Ñù¿ì¡£
µ±Java 7·¢²¼µÄʱºò£¬JVM¾ÍÒѾ֧³ÖÖ´ÐÐеÄ×Ö½ÚÂëÁË£¬µ«ÊDz»¹ÜÌύʲôÑùµÄJava´úÂ룬javac¶¼²»»á²úÉú°üº¬invokedynamicµÄ×Ö½ÚÂë¡£ÕâÏîÌØÐÔÓÃÀ´Ö§³ÖJRubyºÍÆäËûÔËÐÐÔÚJVMÉϵĶ¯Ì¬ÓïÑÔ¡£
ÔÚJava 8ÖУ¬Õâ·¢ÉúÁ˱仯£¬ÔÚʵÏÖlambda±í´ïʽºÍĬÈÏ·½·¨Ê±£¬µ×²ã»áÉú³ÉºÍʹÓÃinvokedynamic£¬Ëüͬʱ»¹»á×÷ΪNashornµÄÊ×Ñ¡·ÖÅÉ»úÖÆ¡£µ«ÊÇ£¬¶ÔÓÚJavaÓ¦ÓõĿª·¢ÈËÔ±À´Ëµ£¬ÒÀȻûÓÐÖ±½ÓµÄ·½Ê½ÊµÏÖÍêÈ«µÄ¶¯Ì¬·½·¨´¦Àí£¨resolution£©¡£Ò²¾ÍÊÇ˵£¬JavaÓïÑÔ²¢Ã»ÓÐÌṩ¹Ø¼ü×Ö»ò¿âÀ´´´½¨Í¨ÓõÄinvokedynamicµ÷Óõ㣨call
site£©¡£ÕâÒâζ×Å£¬¾¡¹ÜÕâÖÖ»úÖÆµÄ¹¦Äܷdz£Ç¿´ó£¬µ«Ëü¶ÔÓÚ´ó¶àÊýµÄJava¿ª·¢ÈËÔ±À´ËµÒÀÈ»ÓÐЩİÉú¡£½ÓÏÂÀ´£¬ÎÒÃÇ¿´Ò»ÏÂÈçºÎÔÚ×Ô¼ºµÄ´úÂëÖÐʹÓÃÕâÏî¼¼Êõ¡£
·½·¨¾ä±ú¼ò½é
ÒªÈÃinvokedynamicÕý³£ÔËÐУ¬Ò»¸öºËÐĵĸÅÄî¾ÍÊÇ·½·¨¾ä±ú£¨method handle£©¡£Ëü´ú±íÁËÒ»¸ö¿ÉÒÔ´Óinvokedynamicµ÷ÓÃµã½øÐе÷Óõķ½·¨¡£ÕâÀïµÄ»ù±¾ÀíÄî¾ÍÊÇÿ¸öinvokedynamicÖ¸Áî¶¼»áÓëÒ»¸öÌØ¶¨µÄ·½·¨¹ØÁª£¨Ò²¾ÍÊÇÒýµ¼·½·¨»òBSM£©¡£µ±½âÊÍÆ÷£¨interpreter£©Óöµ½invokedynamicÖ¸ÁîµÄʱºò£¬BSM»á±»µ÷Óá£Ëü»á·µ»ØÒ»¸ö¶ÔÏ󣨰üº¬ÁËÒ»¸ö·½·¨¾ä±ú£©£¬Õâ¸ö¶ÔÏó±íÃ÷Á˵÷ÓõãҪʵ¼ÊÖ´ÐÐÄĸö·½·¨¡£
ÔÚÒ»¶¨³Ì¶ÈÉÏ£¬ÕâÓë·´ÉäÓÐЩÀàËÆ£¬µ«ÊÇ·´ÉäÓÐËüµÄ¾ÖÏÞÐÔ£¬ÕâЩ¾ÖÏÞÐÔʹËü²»ÊʺÏÓëinvokedynamicÐ×÷ʹÓá£Java
7 APIÖмÓÈëÁËjava.lang.invoke.MethodHandle£¨¼°Æä×ÓÀࣩ£¬Í¨¹ýËüÃÇÀ´´ú±íinvokedynamicÖ¸ÏòµÄ·½·¨¡£ÎªÁËʵÏÖ²Ù×÷µÄÕýÈ·ÐÔ£¬MethodHandle»áµÃµ½JVMµÄÒ»Ð©ÌØÊâ´¦Àí¡£
Àí½â·½·¨¾ä±úµÄÒ»ÖÖ·½Ê½¾ÍÊǽ«ÆäÊÓΪÒÔ°²È«¡¢ÏÖ´úµÄ·½Ê½À´ÊµÏÖ·´ÉäµÄºËÐŦÄÜ£¬ÔÚÕâ¸ö¹ý³Ì»á¾¡¿ÉÄܵر£Ö¤ÀàÐ͵ݲȫ¡£invokedynamicÐèÒª·½·¨¾ä±ú£¬ÁíÍâËüÃÇÒ²¿ÉÒÔµ¥¶ÀʹÓá£
·½·¨ÀàÐÍ
Ò»¸öJava·½·¨¿ÉÒÔÊÓΪÓÉËĸö»ù±¾ÄÚÈÝËù¹¹³É£º
Ãû³Æ
Ç©Ãû£¨°üº¬·µ»ØÀàÐÍ£©
¶¨ÒåËüµÄÀà
ʵÏÖ·½·¨µÄ×Ö½ÚÂë
ÕâÒâζ×ÅÈç¹ûÒªÒýÓÃij¸ö·½·¨£¬ÎÒÃÇÐèÒªÓÐÒ»ÖÖÓÐЧµÄ·½Ê½À´±íʾ·½·¨Ç©Ãû£¨¶ø²»ÊÇ·´ÉäÖÐÇ¿ÖÆÊ¹ÓõÄÁîÈËÌÖÑáµÄClass<?>[]
hack·½Ê½£©¡£
½ÓÏÂÀ´ÎÒÃDzÉÓÃÁíÍâµÄ·½Ê½£¬·½·¨¾ä±úÊ×ÏÈÐèÒªµÄÒ»¸ö¹¹½¨¿é¾ÍÊDZí´ï·½·¨Ç©ÃûµÄ·½Ê½£¬ÒÔ±ãÓÚ²éÕÒ¡£ÔÚJava
7ÒýÈëµÄMethod Handles APIÖУ¬Õâ¸ö½ÇÉ«ÊÇÓÉjava.lang.invoke.MethodTypeÀàÀ´Íê³ÉµÄ£¬ËüʹÓÃÒ»¸ö²»¿É±äµÄʵÀýÀ´´ú±íÇ©Ãû¡£Òª»ñÈ¡MethodType£¬ÎÒÃÇ¿ÉÒÔʹÓÃmethodType()¹¤³§·½·¨¡£ÕâÊÇÒ»¸ö²ÎÊý¿É±ä£¨variadic£©µÄ·½·¨£¬ÒÔclass¶ÔÏó×÷Ϊ²ÎÊý¡£
µÚÒ»¸ö²ÎÊýËùʹÓõÄclass¶ÔÏ󣬶ÔÓ¦×ÅÇ©ÃûµÄ·µ»ØÀàÐÍ£»Ê£Óà²ÎÊýÖÐËùʹÓõÄclass¶ÔÏ󣬶ÔÓ¦×ÅÇ©ÃûÖз½·¨²ÎÊýµÄÀàÐÍ¡£ÀýÈ磺
//toString()µÄÇ©Ãû MethodType mtToString = MethodType.methodType(String.class)
// setter·½·¨µÄÇ©Ãû
MethodType mtSetter = MethodType.methodType(void.class,
Object.class);
// ComparatorÖÐcompare()·½·¨µÄÇ©Ãû
MethodType mtStringComparator = MethodType.methodType(int.class,
String.class, |
ÏÖÔÚÎÒÃǾͿÉÒÔʹÓÃMethodType£¬ÔÙ×éºÏ·½·¨Ãû³ÆÒÔ¼°¶¨Òå·½·¨µÄÀàÀ´²éÕÒ·½·¨¾ä±ú¡£ÒªÊµÏÖÕâÒ»µã£¬ÎÒÃÇÐèÒªµ÷Óþ²Ì¬µÄMethodHandles.lookup()·½·¨¡£ÕâÑùµÄ»°£¬»á¸øÎÒÃÇÒ»¸ö¡°²éÕÒÉÏÏÂÎÄ£¨lookup
context£©¡±£¬Õâ¸öÉÏÏÂÎÄ»ùÓÚµ±Ç°ÕýÔÚÖ´Ðеķ½·¨£¨Ò²¾ÍÊǵ÷ÓÃlookup()µÄ·½·¨£©µÄ·ÃÎÊȨÏÞ¡£
²éÕÒÉÏÏÂÎĶÔÏóÓÐһЩÒÔ¡°find¡±¿ªÍ·µÄ·½·¨£¬ÀýÈ磬findVirtual()¡¢findConstructor()¡¢findStatic()µÈ¡£ÕâЩ·½·¨½«»á·µ»ØÊµ¼ÊµÄ·½·¨¾ä±ú£¬ÐèҪעÒâµÄÊÇ£¬Ö»ÓÐÔÚ´´½¨²éÕÒÉÏÏÂÎĵķ½·¨Äܹ»·ÃÎÊ£¨µ÷Ó㩱»ÇëÇó·½·¨µÄÇé¿öÏ£¬²Å»á·µ»Ø¾ä±ú¡£ÕâÓë·´É䲻ͬ£¬ÎÒÃÇûÓÐ°ì·¨ÈÆ¹ý·ÃÎÊ¿ØÖÆ¡£»»¾ä»°Ëµ£¬·½·¨¾ä±úÖв¢Ã»ÓÐÓësetAccessible()¶ÔÓ¦µÄ·½·¨¡£ÀýÈ磺
public MethodHandle getToStringMH() { MethodHandle mh = null; MethodType mt = MethodType.methodType(String.class); MethodHandles.Lookup lk = MethodHandles.lookup();
try {
mh = lk.findVirtual(getClass(), "toString",
mt);
} catch (NoSuchMethodException | IllegalAccessException
mhx) {
throw (AssertionError)new AssertionError().initCause(mhx);
}
return mh;
} |
MethodHandleÖÐÓÐÁ½¸ö·½·¨Äܹ»´¥·¢¶Ô·½·¨¾ä±úµÄµ÷Óã¬ÄǾÍÊÇinvoke()ºÍinvokeExact()¡£ÕâÁ½¸ö·½·¨¶¼ÊÇÒÔ½ÓÊÕÕߣ¨receiver£©ºÍµ÷ÓñäÁ¿×÷Ϊ²ÎÊý£¬ËùÒÔËüÃǵÄÇ©ÃûΪ£º
public final Object invoke(Object... args) throws Throwable; public final Object invokeExact(Object... args) throws Throwable;
|
Á½ÕßµÄÇø±ðÔÚÓÚ£¬invokeExact()ÔÚµ÷Ó÷½·¨¾ä±úʱ»áÊÔͼÑϸñµØÖ±½ÓÆ¥ÅäËùÌṩµÄ±äÁ¿¡£¶øinvoke()ÓëÖ®²»Í¬£¬ÔÚÐèÒªµÄʱºò£¬invoke()Äܹ»ÉÔ΢µ÷ÕûһϷ½·¨µÄ±äÁ¿¡£invoke()»áÖ´ÐÐÒ»¸öasType()ת»»£¬Ëü»á¸ù¾ÝÈçϵÄÕâ×鹿ÔòÀ´½øÐбäÁ¿µÄת»»£º
Èç¹ûÐèÒªµÄ»°£¬ÔʼÀàÐÍ»á½øÐÐ×°Ïä²Ù×÷
Èç¹ûÐèÒªµÄ»°£¬×°ÏäºóµÄÔʼÀàÐÍ»á½øÐвðÏä²Ù×÷
Èç¹û±ØÒªµÄ»°£¬ÔʼÀàÐÍ»á½øÐÐÀ©Õ¹
void·µ»ØÀàÐÍ»áת»»Îª0£¨¶ÔÓÚ·µ»ØÔʼÀàÐ͵ÄÇé¿ö£©£¬¶ø¶ÔÓÚÔ¤ÆÚµÃµ½ÒýÓÃÀàÐ͵ķµ»ØÖµµÄµØ·½£¬½«»áת»»Îªnull
nullÖµ»á±»ÊÓΪÕýÈ·µÄ£¬²»¹Ü¾²Ì¬ÀàÐÍÊÇʲô¶¼¿ÉÒÔ½øÐд«µÝ
½ÓÏÂÀ´£¬ÎÒÃÇ¿´Ò»Ï¿¼ÂÇÉÏÊö¹æÔòµÄ¼òµ¥µ÷ÓÃÑùÀý£º
Object rcvr = "a"; try { MethodType mt = MethodType.methodType(int.class); MethodHandles.Lookup l = MethodHandles.lookup(); MethodHandle mh = l.findVirtual(rcvr.getClass(), "hashCode", mt);
int ret;
try {
ret = (int)mh.invoke(rcvr);
System.out.println(ret);
} catch (Throwable t) {
t.printStackTrace();
}
} catch (IllegalArgumentException | NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
}
|
ÔÚ¸üΪ¸´ÔÓµÄÑùÀýÖУ¬·½·¨¾ä±úÄܹ»ÒÔ¸üÇåÎúµÄ·½Ê½À´Ö´ÐÐÓëºËÐÄ·´É书ÄÜÏàͬµÄ¶¯Ì¬±à³ÌÈÎÎñ¡£³ý´ËÖ®Í⣬ÔÚÉè¼ÆÖ®³õ£¬·½·¨¾ä±ú¾ÍÓëJVMµ×²ãµÄÖ´ÐÐÄ£ÐÍÐ×÷µØ¸üºÃ£¬²¢ÇÒ¿ÉÄÜ»áÌṩ¸üºÃµÄÐÔÄÜ£¨¾¡¹ÜÐÔÄܵÄÎÊÌ⻹ûÓÐÕ¹¿ªÐðÊö£©¡£
·½·¨¾ä±úÓëinvokedynamic
invokedynamicÖ¸Áîͨ¹ýÒýµ¼·½·¨£¨bootstrap method£¬BSM£©»úÖÆÀ´Ê¹Ó÷½·¨¾ä±ú¡£ÓëinvokevirtualÖ¸Áͬ£¬invokedynamicÖ¸ÁîûÓнÓÊÕÕß¶ÔÏó¡£Ïà·´£¬ËüÃǵÄÐÐΪÀàËÆÓÚinvokestatic£¬»áʹÓÃBSMÀ´·µ»ØÒ»¸öCallSiteÀàÐ͵ĶÔÏó¡£Õâ¸ö¶ÔÏó°üº¬Ò»¸ö·½·¨¾ä±ú£¨³ÆÖ®Îª¡°target¡±£©£¬Ëü´ú±íÁ˵±Ç°invokedynamicÖ¸ÁîÒªÖ´Ðеķ½·¨¡£
µ±°üº¬invokedynamicµÄÀà¼ÓÔØÊ±£¬µ÷Óõã»á´¦ÓÚ¡°unlaced¡±×´Ì¬£¬ÔÚBSM·µ»ØÖ®ºó£¬µÃµ½µÄCallSiteºÍ·½·¨¾ä±ú»áÈõ÷Óõ㴦ÓÚ¡°laced¡±×´Ì¬¡£
BSMµÄÇ©Ãû´óÖ»áÈçÏÂËùʾ£¨×¢Ò⣬BSMµÄÃû³ÆÊÇÈÎÒâµÄ£©£º
static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type);
|
Èç¹ûÄãÏ£Íû´´½¨°üº¬invokedynamicµÄ´úÂ룬ÄÇôÎÒÃÇÐèҪʹÓÃÒ»¸ö×Ö½ÚÂë²Ù×ݿ⣨ÒòΪJavaÓïÑÔ±¾Éí²¢²»°üº¬ÎÒÃÇËùÐèµÄ¹¹Ô죩¡£ÔÚ±¾ÎÄÊ£ÓàµÄÄÚÈÝÖУ¬ÎÒÃǽ«»áʹÓÃASM¿âÀ´Éú³É°üº¬invokedynamicÖ¸ÁîµÄ×Ö½ÚÂë¡£´ÓJavaÓ¦ÓóÌÐòµÄ½Ç¶ÈÀ´¿´£¬ËüÃÇ¿´ÆðÀ´¾ÍÏñÊdz£¹æµÄÀàÎļþ£¨µ±È»£¬ËüÃÇûÓÐÏà¹ØµÄJavaÔ´Âë±íÊö£©¡£Java´úÂë»á½«ÆäÊÓΪ¡°ºÚºÐ¡±£¬²»¹ýÎÒÃÇ¿ÉÒÔµ÷Ó÷½·¨²¢Ê¹ÓÃinvokedynamic¼°ÆäÏà¹ØµÄ¹¦ÄÜ¡£
ÏÂÃæ£¬ÎÒÃÇÀ´¿´Ò»Ï»ùÓÚASMµÄÀ࣬Ëü»áʹÓÃinvokedynamicÖ¸ÁîÀ´Éú³É¡°Hello World¡±¡£
public class InvokeDynamicCreator {
public static void main(final String[] args)
throws Exception {
final String outputClassName = "kathik/Dynamic";
try (FileOutputStream fos
= new FileOutputStream(new File("target/classes/"
+ outputClassName + ".class"))) {
fos.write(dump(outputClassName, "bootstrap",
"()V"));
}
}
public static byte[] dump(String outputClassName,
String bsmName, String targetMethodDescriptor)
throws Exception {
final ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
// ΪÒýµ¼Àà´î½¨»ù±¾µÄÔªÊý¾Ý
cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, outputClassName,
null, "java/lang/Object", null);
// ´´½¨±ê×¼µÄvoid¹¹ÔìÆ÷
mv = cw.visitMethod(ACC_PUBLIC, "",
"()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object",
"", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
// ´´½¨±ê×¼µÄmain·½·¨
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
"([Ljava/lang/String;)V", null, null);
mv.visitCode();
MethodType mt = MethodType.methodType(CallSite.class,
MethodHandles.Lookup.class, String.class,
MethodType.class);
Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC,
"kathik/InvokeDynamicCreator", bsmName,
mt.toMethodDescriptorString());
mv.visitInvokeDynamicInsn("runDynamic",
targetMethodDescriptor, bootstrap);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
private static void targetMethod() {
System.out.println("Hello World!");
}
public static CallSite bootstrap(MethodHandles.Lookup
caller, String name, MethodType type) throws NoSuchMethodException,
IllegalAccessException {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
// ÐèҪʹÓÃlookupClass()£¬ÒòΪÕâ¸ö·½·¨ÊǾ²Ì¬µÄ
final Class currentClass = lookup.lookupClass();
final MethodType targetSignature = MethodType.methodType(void.class);
final MethodHandle targetMH = lookup.findStatic(currentClass,
"targetMethod", targetSignature);
return new ConstantCallSite(targetMH.asType(type));
}
} |
Õâ¸ö´úÂë·ÖΪÁ½²¿·Ö£¬µÚÒ»²¿·ÖʹÓÃASM Visitor APIÀ´´´½¨ÃûΪkathik.DynamicµÄÀàÎļþ¡£×¢Ò⣬ºËÐĵĵ÷ÓÃÊÇvisitInvokeDynamicInsn()¡£µÚ¶þ²¿·Ö°üº¬ÁËÒªÀ¦°óµ½µ÷ÓõãÖеÄÄ¿±ê·½·¨£¬²¢ÇÒ»¹°üÀ¨invokedynamicÖ¸ÁîËùÐèµÄBSM¡£
×¢Ò⣬ÉÏÊöµÄ·½·¨ÊÇλÓÚInvokeDynamicCreatorÀàÖе쬶ø²»ÊÇËùÉú³ÉµÄkathik.DynamicÀàµÄÒ»²¿·Ö¡£ÕâÒâζ×Å£¬ÔÚÔËÐÐʱ£¬InvokeDynamicCreator±ØÐëÒ²ÒªºÍkathik.DynamicÒ»ÆðλÓÚÀà·¾¶ÖУ¬·ñÔòµÄ»°£¬¾Í»áÎÞ·¨ÕÒµ½·½·¨¡£
µ±InvokeDynamicCreatorÔËÐÐʱ£¬Ëü»á´´½¨Ò»¸öеÄÀàÎļþDynamic.class£¬Õâ¸öÎļþÖаüº¬ÁËinvokedynamicÖ¸Áͨ¹ýÔÚÕâ¸öÀàÉÏÖ´ÐÐjavap£¬ÎÒÃÇ¿ÉÒÔ¿´µ½ÕâÒ»µã£º
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=0, locals=1, args_size=1 0: invokedynamic #20, 0 // InvokeDynamic #0:runDynamic:()V 5: return
|
Õâ¸öÑùÀý²ûÊöÁËinvokedynamic×î¼òµ¥µÄʹÓó¡¾°£¬Ëü»áʹÓÃÒ»¸öÌØ¶¨µÄ³£Á¿CallSite¶ÔÏó¡£ÕâÒâζ×ÅBSM£¨ºÍlookup£©Ö»»áÖ´ÐÐÒ»´Î£¬ËùÒÔºóÐøµÄµ÷ÓûáºÜ¿ì¡£
µ«ÊÇ£¬Õë¶ÔinvokedynamicµÄ¸ß¼¶Ó÷¨ºÜ¿ì¾Í»á±äµÃ·Ç³£¸´ÔÓ£¬µ±µ÷ÓõãºÍÄ¿±ê·½·¨ÔÚ³ÌÐòÉúÃüÖÜÆÚÖлᷢÉú±ä»¯Ê±¸üÊÇÈç´Ë¡£
|