关于Class的invokeDynamic指令
(2)invokedynamic指令 https://www.cnblogs.com/wade-luffy/p/6058087.html
public class InDyTest {
public static void main(String[] args) {
Runnable x = () -> {
//System.out.println("Hello, World!");
};
}
}
生成的Class结构如下:
Classfile /C:/Users/mazhi/Desktop/InDyTest.class
Last modified 2018-7-5; size 986 bytes
MD5 checksum 03d0c485e603b294e8de271d879c7b8f
Compiled from "InDyTest.java"
public class com.test01.InDyTest
SourceFile: "InDyTest.java"
BootstrapMethods:
0: #34 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/la ng/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Lj ava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/Meth odType;)Ljava/lang/invoke/CallSite;
Method arguments:
#35 ()V
#38 invokestatic com/test01/InDyTest.lambda$0:()V
#39 ()V
InnerClasses:
public static final #45= #41 of #43; //Lookup=class java/lang/invoke/Meth odHandles$Lookup of class java/lang/invoke/MethodHandles
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // com/test01/InDyTest
#2 = Utf8 com/test01/InDyTest
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Methodref #3.#9 // java/lang/Object."<init>":()V
#9 = NameAndType #5:#6 // "<init>":()V
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/test01/InDyTest;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = NameAndType #17:#18 // run:()Ljava/lang/Runnable;
#17 = Utf8 run
#18 = Utf8 ()Ljava/lang/Runnable;
#19 = InvokeDynamic #0:#16 // #0:run:()Ljava/lang/Runnable;
#20 = Utf8 args
#21 = Utf8 [Ljava/lang/String;
#22 = Utf8 x
#23 = Utf8 Ljava/lang/Runnable;
#24 = Utf8 lambda$0
#25 = Utf8 SourceFile
#26 = Utf8 InDyTest.java
#27 = Utf8 BootstrapMethods
#28 = Methodref #29.#31 // java/lang/invoke/LambdaMetafactory .metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lan g/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle; Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#29 = Class #30 // java/lang/invoke/LambdaMetafactory
#30 = Utf8 java/lang/invoke/LambdaMetafactory
#31 = NameAndType #32:#33 // metafactory:(Ljava/lang/invoke/Met hodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invo ke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava /lang/invoke/CallSite;
#32 = Utf8 metafactory
#33 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/St ring;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke /MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#34 = MethodHandle #6:#28 // invokestatic java/lang/invoke/Lamb daMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/Str ing;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/ MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#35 = MethodType #6 // ()V
#36 = Methodref #1.#37 // com/test01/InDyTest.lambda$0:()V
#37 = NameAndType #24:#6 // lambda$0:()V
#38 = MethodHandle #6:#36 // invokestatic com/test01/InDyTest.l ambda$0:()V
#39 = MethodType #6 // ()V
#40 = Utf8 InnerClasses
#41 = Class #42 // java/lang/invoke/MethodHandles$Loo kup
#42 = Utf8 java/lang/invoke/MethodHandles$Lookup
#43 = Class #44 // java/lang/invoke/MethodHandles
#44 = Utf8 java/lang/invoke/MethodHandles
#45 = Utf8 Lookup
{
public com.test01.InDyTest();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init> ":()V
4: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/test01/InDyTest;
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=2, args_size=1
0: invokedynamic #19, 0 // InvokeDynamic #0:run:()Ljava/la ng/Runnable;
5: astore_1
6: return
LineNumberTable:
line 7: 0
line 10: 6
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 args [Ljava/lang/String;
6 1 1 x Ljava/lang/Runnable;
}
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import static java.lang.invoke.MethodHandles.lookup;
public class TestMethod {
static class ClassA {
public void println(String s) {
System.out.println(s);
}
}
public static void main(String[] args) throws Throwable {
Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
/*
* 无论obj最终是哪个实现类,下面这句都能正确调用到println方法
**/
getPrintlnMH(obj).invokeExact("icyfenix");
}
private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable {
/*
* MethodType:代表“方法类型”,包含了方法的返回值(methodType()的第一个参数)
* 和具体参数(methodType() 第二个及以后的参数)
*/
MethodType mt = MethodType.methodType(void.class, String.class);
/*
* lookup()方法来自于MethodHandles.lookup,这句的作用是在指定类中查找符合给定的方法名称、方法类型,
* 并且符合调用权限的方法句柄
* 因为这里调用的是一个虚方法,按照Java语言的规则,方法第一个参数是隐式的,代表该方法的接收者,也即是this指向的对象,
* 这个参数以前是放在参数列表中进行传递的,而现在提供了bindTo()方法来完成这件事情
*/
return lookup().findVirtual(reveiver.getClass(), "println", mt).bindTo(reveiver);
}
}
import static java.lang.invoke.MethodHandles.lookup;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class InvokeDynamicTest {
public static void main(String[] args) throws Throwable {
INDY_BootstrapMethod().invokeExact("icyfenix");
}
public static void testMethod(String s) {
System.out.println("hello String:" + s);
}
public static CallSite BootstrapMethod(
MethodHandles.Lookup lookup,
String name,
MethodType mt) throws Throwable {
return new ConstantCallSite(
lookup.findStatic(InvokeDynamicTest.class, name, mt));
}
private static MethodType MT_BootstrapMethod() {
return MethodType.fromMethodDescriptorString(
"(Ljava/lang/invoke/MethodHandles $Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
null);
}
private static MethodHandle MH_BootstrapMethod() throws Throwable {
return lookup().findStatic(
InvokeDynamicTest.class,
"BootstrapMethod",
MT_BootstrapMethod());
}
private static MethodHandle INDY_BootstrapMethod() throws Throwable {
CallSite cs = (CallSite) MH_BootstrapMethod().invokeWithArguments(
lookup(),
"testMethod",
MethodType.fromMethodDescriptorString("(Ljava/lang/String;)V", null));
return cs.dynamicInvoker();
}
}
import static java.lang.invoke.MethodHandles.lookup;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
public class Test02 {
class GrandFather {
void thinking() {
System.out.println("i am grandfather");
}
}
class Father extends GrandFather {
void thinking() {
System.out.println("i am father");
}
}
class Son extends Father {
void thinking() {
try {
MethodType mt = MethodType.methodType(void.class);
MethodHandle mh = lookup().findVirtual(
GrandFather.class,
"thinking",
mt)
.bindTo(new Test02().new GrandFather());
mh.invokeExact();
} catch (Throwable e) {
}
}
}
public static void main(String[] args) {
(new Test02().new Son()).thinking();
}
}
关于Class的invokeDynamic指令的更多相关文章
- invokedynamic指令
Java虚拟机的字节码指令集的数量从Sun公司的第一款Java虚拟机问世至JDK 7来临之前的十余年时间里,一直没有发生任何变化.随着JDK 7的发布,字节码指令集终于迎来了第一位新成员--invok ...
- 方法引用(Method reference)和invokedynamic指令详细分析
方法引用(Method reference)和invokedynamic指令详细分析 invokedynamic是jvm指令集里面最复杂的一条.本文将详细分析invokedynamic指令是如何实现方 ...
- 动态方法调用秘密武器 —— invokedynamic 指令解读 - MethodHandle
原文:https://juejin.im/book/5c25811a6fb9a049ec6b23ee/section/5ccc66dd518825403b5975fb import java.lang ...
- invokedynamic字节码指令
1. 方法引用和invokedynamic invokedynamic是jvm指令集里面最复杂的一条.本文将从高观点的角度下分析invokedynamic指令是如何实现方法引用(Method refe ...
- JVM-字节码指令
Java虚拟机字节码指令 了解了class文件,我觉得就很有必要去了解一下JVM中的字节码指令,那样堆class文件以及JVM运行机制也后很大的帮助. Java虚拟机的指令由一个字节长度的,代表着某种 ...
- Scripting Java #3:Groovy与invokedynamic
只需看看今天Groovy语言实现机制.在此之前,是第一个推倒静态类型与动态类型语言在实现上面的一些差异. 静态类型 vs. 动态类型 看以下这个简单的栗子. def addtwo(a, b) { re ...
- java7 invokedynamic命令深入研究
在看java虚拟机字节码执行引擎的时候,里面提到了java虚拟机里调用方法的字节码指令有5种: invokestatic //调用静态方法 invokespecial //调用私有方法.实例构造器方法 ...
- jvm理论-字节码指令
Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成. 基本数据类型 1.除了l ...
- Java字节码指令
1. 简介 Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码)以及跟随其后的零至多个代表此操作所需参数(称为操作数)而构成. 由于Java虚拟机采用面向操作数栈而不是寄存 ...
随机推荐
- spring案列——xml配置
一.需要的jar包 spring.jar(官网下载) commons-logging.jar 二.项目结构 三.entity(实体类) package com.team.model; public c ...
- Feed back TFS 2017 RC upgrade status to product team in product group 2017.03.01
作为微软的MVP,有一个我最喜欢的好处,就是可以与产品组(产品研发部门)有零距离接触,可以最先拿到即将发版的产品,并且和产品组沟通,对产品中出现的问题实时反馈. 看到TFS产品组吸收了自己的建议和反馈 ...
- DAC--解决windows验证无法登陆的问题
解决思路: 使用单用户管理员模式启动SQL Server,再使用SQLCMD连接上数据库,此时有sysadmin权限,添加用户并赋予相应权限 1>停止SQL Server服务运行 2>在C ...
- webapi 用腾讯云手机短信验证码
#region 验证码相关 public class SmsSDK { #region 短信发送的必要参数 /// <summary> /// appId /// </summary ...
- 5.WebAPI的Filter
1.WebApi的Filter介绍: 大家知道什么是AOP(aspect oriented programming)吗?它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添 ...
- Python3------反射详解
反射: 根据字符串动态的判断,调用,添加/修改,删除类或类的实例化对象中的方法或属性 反射共有四种方法hasattr(),getattr(),setattr(),delattr() 1.通过字符串来判 ...
- web窗体ListView配置分页
一.配置objectDataSource 1.选择业务逻辑层的类,再选择对应的分页方法 2.配置Select对应的方法,必须是一个带两个整型参数的方法,第一个参数表示要查看的第一条记录的前一条,第二个 ...
- bootstrap-treeview 加载默认选择第一个节点
configAppTree: function (oArrayData){ $('#appTree').treeview({ color: "#545454", expandIco ...
- php类模块引擎PDO操作MySQL数据库简单阐述
PDO是什么呢? 通俗说就是别人写的一个“数据库操作工具类”,它非常强大,可以应对市面上几乎所有主流数据库, 具体应用时候有这样一个关系: 即,要操作某种数据,就得去“打开”对应的pdo引擎. 在ph ...
- WPF之坑——surface触控失灵之谜
本次又遇到了WPF编写触控程序的一个问题,虽然已解决,但原因确搞不太明白,希望有大神看到这篇文章帮我解答. 在项目中实现了自己定义的icommandsource,因为需要对触控有特殊需求,控件对鼠标与 ...