共计 2551 个字符,预计需要花费 7 分钟才能阅读完成。
前言
上一节讲述了栈桢和分派的细节,这一节咱们来讲讲自 java 语言诞生新减少的新语言个性:动静类型语言反对,这一节将会依据动静语言的个性以及相干的介绍同时讲述 jvm 一个重要的指令:invoke dynamic 指令。然而须要留神的是:invokedy namic 指令面向 的次要服务对象并非 Java 语言,而是其余 Java 虚拟机之上的其余动静类型语言
概述
- 介绍什么是动静类型语言,以及 java 为什么是动态语言的解说。
- 介绍 invokeDynamic 指令在理论案例中的使用
- 介绍 java 实现动静语言调用的一些曲线救国的伎俩。
动静类型语言
什么是动静类型语言
动静类型语言的要害特色是它的类型查看的主体过程是在运行期而不是编译期。而 java 就是典型的动态类型语言,须要在编码的过程中确定的,动态的语言也意味着所有的类型在编译器必须确定。
为什么 java 是动态类型?
这里牵扯到一个问题就是为什么 java 是动态类型呢?咱们能够看一下 invokeVitual 命令,这个命令依据如下的内容,确定一个属性的全类名,以及类型,在符号援用的阶段能够看到根本的内容:
invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
这些符号援用在翻译为间接援用是须要确切的类型的,所以在晚期的 java 天生不足动静语言的反对。
动静语言类型反对
java 在 jdk7 之后退出了动静语言反对,对于退出动静语言类型的反对外围是应用 invoke dynamic 命令,这种形式应用了相似曲线救国的形式,也是为兼容思考不得不做的一种斗争,比方最常见的类型数组,在 java 中咱们必须声明确数组寄存的类型,而 jdk 引入了 invokeDynamic 这个指令之后,就能够实现对于一个办法参数的动静调用。
动静类型语言是能够让对象的类型能够在运行时候再确定,比方 JS 和 Python 的 var。
invokedynamic 指令
上面来说下 invoke 这个指令是如何实现动静类型语言的,在 java 中是无奈把一个函数作为参数传递的,更多的形式应用相似实现接口的形式进行解决,而新的指令在某种程度上是应用相似 MethodHandle 的形式进行解决的,MethodHandle 是对通过字节码的办法指令调用的模仿,但和反射不同的是反射是基于 Java 语言服务的,而 MethodHandler 则是服务于所有虚拟机上的一种语言。
每一处含有 invokedynamic 指令的地位都被称作“动静调用点 (Dynamically-Computed Call Site)”,这条指令的第一个参数不再是代表办法符号援用的 CONSTANT_Methodref_info 常量,而是变为 JDK 7 时新退出的 CONSTANT_InvokeDynamic_info 常量,从这个新常量中能够失去 3 项信息: 疏导办法 (Bootstrap Method,该办法寄存在新增的 BootstrapMethods 属性中)、办法类型 (MethodType) 和 名称。
为了更好的了解这个命令,上面咱们来看下理论运行过程当中的利用,比方在 jdk8 中引入的 lambada 表达式和默认办法就是通过 invokedynamic 命令实现的,然而应用 jdk8 的实现看起来比拟难以了解,上面来看一下书中给的一段案例代码:
Constant pool:
#121 = NameAndType #33:#30 // testMethod:(Ljava/lang/String;)V #123 = InvokeDynamic #0:#121 // #0:testMethod:(Ljava/lang/String;)V
public static void main(java.lang.String[]) throws java.lang.Throwable; Code:
stack=2, locals=1, args_size=1
0: ldc #23 // String abc
2: invokedynamic #123, 0 // InvokeDynamic #0:testMethod: (Ljava/lang/String;)V 7: nop
8: return
public static java.lang.invoke.CallSite BootstrapMethod(java.lang.invoke.Method Handles$Lookup, java.lang.Strin Code:
stack=6, locals=3, args_size=3
0: new
3: dup
4: aload_0
5: ldc
7: aload_1
8: aload_2
9: invokevirtual #65
12: invokespecial #71 15: areturn
#63
#1
// class java/lang/invoke/ConstantCallSite
// class org/fenixsoft/InvokeDynamicTest
// Method java/lang/invoke/MethodHandles$ Lookup.findStatic:(Ljava/lang/Cl // Method java/lang/invoke/ConstantCallSite. "<init>":(Ljava/lang/invoke/M
从下面的办法调用能够看到,应用的是 invokeDynamic 的调用指令以及参数为第 123 项的常量,比方如下的内容:
2: invokedynamic #123, 0 // InvokeDynamic #0:testMethod:(Ljava/lang/String;)V
而 BootstrapMethod()办法中指令将会产生 testMethod()办法,当然这个办法在 java 源码中是看不见的,而是由 invokeDynamic 动静生成的一个办法,当指令实现对应的办法调用之后,这个指令的调用过程也宣告完结了。
总结
本文的内容比拟啊间断,次要针对动静类型语言做了一个补充,内容比拟剪短,至此,jvm 的内容大抵以及全副讲述结束,而对于书中的最初一节并发编程的形容,集体将会放到《并发编程实战》中进行总结(又得回去看一遍)。
写在最初
invokeDynamic 次要服务的是其余语言的接入,然而从实际效果来看不是非常的现实。