InvokedynamicJava的秘密武器
最早关于invokedynamic的工作至少可以追溯到2007年,首次成功进行的动态调用是在2008年8月26日进行的。这早于Sun被Oracle收购之前,并且按照大多数开发人员的标准,该功能已经开发了很长时间。 。 invokedynamic的卓越之处在于它是自Java 1.0以后的第一个新增的字节码。它加入了现有的调用字节码invokevirtual,invokestatic,invokeinterface和invokespecial。这四个现有操作码实现了Java开发人员通常熟悉的所有形式的方法分派,特别是: invokevirtual -实例方法的标准调用invokestatic -用于分派静态方法invokeinterface -用于通过接口调用方法invokespecial -在需要非虚拟(即“精确”)调度时使用一些开发人员可能对平台为何需要全部四个操作码感到好奇,所以让我们看一个使用不同的调用操作码的简单示例,以说明它们之间的区别: public class InvokeExamples { public static void main(String[] args) { InvokeExamples sc = new InvokeExamples(); sc.run(); } private void run() { List<String> ls = new ArrayList<>(); ls.add("Good Day"); ArrayList<String> 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."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class kathik/InvokeExamples 3: dup 4: invokespecial #3 // Method "<init>":()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."<init>":()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."<init>":()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处): ...