java invokedynamic虚拟机指令

阅读数:52 评论数:0

跳转到新版页面

分类

python/Java

正文

一、概述

1、jvm虚拟机指令

(1)常用指令

new 创建一个对象并将地址放入虚拟机栈
dup 复制一个对象地址放入虚拟机栈
invokespecial 用于调用构造方法、私有方法及final方法
invokevirtual 用于调用普通的需要动态加载的方法
invokestatic 用于调用静态方法
invokeinterface 用于调用接口方法
checkcast 确定对象为所给定的类型并强制类型转换
putstatic 设置类中静态字段的值
getstatic 从类中获取静态字段
putfield 设置对象中字段的值
getfield 从对象中获取字段
instanceof 判断对象是否为给定的类型
pop 将上面执行的最近的栈顶数值弹出栈
istore_0 将上面执行最近的引用地址放入局部变量表第零个槽位(相应的 i 可以替换为s,l,f,d,a,ia,ba,sa,la,fa,da,ca,aa,分别指代int,short,long,float,double,引用类型,int数组,boolean数组,short数组,long数组,float数组,double数组,char数组,引用类型数组)
iload_1 将局部变量表中第一个槽位的值或地址放入虚拟机栈(相应的 i 可以替换为s,l,f,d,a,ia,ba,sa,la,fa,da,ca,aa,分别指代int,short,long,float,double,引用类型,int数组,boolean数组,short数组,long数组,float数组,double数组,char数组,引用类型数组)
iconst_1 当int取值-1~5时,取一个常量放入虚拟机栈(相应的前面的i:int类型,可替换为除了byte的其它几种基本数据类型)。
bipush int取值-128~127时, 认为是一个byte类型的值放入虚拟机栈
sipush 当int取值-32768~32767时,认为是short类型的值放入虚拟机栈。
ldc 用于将int、float、String类型常量从常量池中压到虚拟机栈
goto 跳转到某行指令
return 返回方法命令

(2)运算指令

相应的i可以替换为s、l、f、d,分别指代int、short、long、float、double。

iadd int类型的加法
isub int类型的减法
imul int类型的乘法
idiv int类型的除法
irem int类型的除法的余数
ineg int类型的取反操作
iinc int类型的本身加上一个常量

(3)流程控制

相应的i可以替换为s、l、f、d,分别指代int、short、long、float、double。

ifeq 是否等于0
ifne 是否不等于0
iflt 是否小于0
ifge 是否大于等于0
ifgt 是否大于0
ifle 是否小于等于0
if_icmpeq 判断两个值是否相等
if_icmpne 判断两个值是否不相等
if_icmplt 判断先入栈的是否小于后入栈的
if_icmple 判断先入栈的是否小于等于后入栈的
if_icmpge 判断先入栈的是否大于等于后入栈的
if_icmpgt 判断先入栈的是否大于后入栈的
ifnull 判断是否为null
ifnonnull 判断是否不为null

(4)比较

lcmp 比较两个值long类型值
fcmpl 比较float类型值(当遇到NaN时,返回-1)
fcmpg 比较float类型值(当遇到NaN时,返回1)
dcmpl 比较double类型值(当遇到NaN时,返回-1)
dcmpg 比较double类型值(当遇到NaN时,返回1)

2、invokedynamic

invokedynamic是java 7引入的一条虚拟机指令,到java 8后被应用到lambda表达式中。invokedynamic与其它invoke指令不同的是它允许应用级的代码来决定方法解析。这个应用级代码被称为引导方法(Bootstrap Method),简称BSM。BSM返回一个CallSite对象,CallSite就是一个MethodHandle的holder,这个MethodHandle指向真正要执行的方法,这个CallSite和invokedynamic链接在一起,以后再执行这条invokedynamic指令都不会创建新的CallSite对象。

二、MethodHandle

通过MethodHandle可以调用method、construct、field,比起反射更强大的是,Method Handle还可以调用到父类的方法。

class Example {
 void doSomething() {
 MethodHandles.Lookup lookup = MethodHandles.lookup();
 }
 private void foo() { /* ... */ }
}

MethodHandle不能直接初始化,可以使用MethodHandles类提供的工厂方法,lookup对象仅仅能定位到Example类可见的属性,比如说foo方法,其它类中对Exampe类不可见的私有方法是定位不到的。

1、MethodType

一个Method handle只能持有一个指定具体类型的方法,方法的类型包括返回类型和参数类型。

可以使用MethodType来描述方法的类型。

class Counter {
 static int count(String name) {
 return name.length();
 }
}

MethodType methodType = MethodType.methodType(int.class, new Class<?>[] {String.class});

MethodHandles.Lookup lookup = MethodHandles.lookup();

MethodHandle methodHandle = lookup.findStatic(Counter.class, "count", methodType);

int count = methodHandle.invokeExact("foo");

assertThat(count, is(3));

通过上面创建的lookup和methodType,可以用来定位Counter类的count方法。

Java中的每个方法都有一个独特的方法签名,签名由方法名、方法参数组成。虽然语言层面上不允许通过改变方法返回类型来进行方法的重载,但是字节码层面是允许的

2、访问Field

public class Bean {
    String value;

    void print(String x) {
        System.out.println(x);
    }
}

MethodHandle fieldHandle = lookup.findSetter(Bean.class, "value", String.class);
MethodType methodType = MethodType.methodType(void.class, new Class<?>[] {String.class});
MethodHandle methodHandle = lookup.findVirtual(Bean.class, "print", methodType);

使用Methods.Lookup对象,可以获取对变量的引用。如果想要设置一个变量可以使用findSetter方法,想要读取一个变量,可以使用findGetter方法。

3、与反射Method的区别

(1)Reflection和MethodHandle机制本质上都是在模拟方法调用,但是Refelction是在模拟Java代码层次的方法调用,而MethodHandle是在模拟字节码层次的方法调用。

在MethodHandles.Lookup上的三个方法findStatic()、findVirtual()、findSpecial()正是为了对应于invokestatic、invokevirtual & invokeinterface和invokespecial这几条字节码指令的执行权限校验行为,而这些底层细节在使用Reflection API时是不需要关心的。

(2)java.lang.reflect.Method对象远比MethodHandle机制中的java.lang.invoke.MethodHandle对象所包含的信息来得多。前者是方法在Java一端的全面映像,包含了方法的签名、描述符以及方法属性表中各种属性的Java端表示方式,还包含有执行权限等的运行期信息。而后者仅仅包含着与执行该方法相关的信息。




相关推荐

方式1:通过@PostConstruct和@PreDestroy方法。 从Java EE5开始,Servlet增加了两个影响Servlet生命周期的注解。 方式2:通

一、概述 1、spring容器 spring中有三种bean容器:BeanFactory、ApplicationContext、WebApplicationContext。 (1)BeanFactor

@Configuration(proxyBeanMethods = false) @ConditionalOnProperty(prefix = "spring.mail", name = "host

一、概述 HandlerMapping 组件负责为请求找到合适的 HandlerExecutionChain 处理器执行链,包含处理器(handler)和拦截器们(interceptors)。 1、h

当参数类型为json时,通过 Request().getParameterMap() 是获取不到参数的,可以通过  JSONObject.toJSONString(joinPoint.getArgs(

一、概述 Spring 中的处理器的实现多变,比如用户的处理器可以实现 Controller 接口或者 HttpRequestHandler 接口,也可以用 @RequestMapping 注解将方法

一、概述 @RequestMapping注解是一个用来处理请求地址映射的注解,可用于映射一个请中一个方法 ,可以用在类或方法上。 二、@RequestMapping的属性 1、value属性 @Req