java自建ocr完整示例_Java 7:完整的invokedynamic示例

java自建ocr完整示例

我当前的Java 7系列中的另一个博客条目。 这次它处理的是invokedynamic,这是JVM上用于方法调用的新字节码指令。 invokedynamic指令允许呼叫站点与呼叫接收者之间的动态链接。

这意味着您可以将正在执行方法调用的类链接到在运行时正在接收调用的类(和方法)。 用于方法调用的所有其他JVM字节码指令,例如invokevirtual ,将目标类型信息硬连线到编译中,即硬连线到类文件中。 让我们来看一个例子。

Constant pool:#1 = Class              #2             //  com/schlimm/bytecode/examples/BytecodeExamples...#42 = Class              #43            //  java/lang/String...#65 = Methodref          #42.#66        //  java/lang/String.length:()I#66 = NameAndType        #67:#68        //  length:()I#67 = Utf8               length#68 = Utf8               ()I...
{...public void virtualMethodCall();flags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: ldc           #44                 // String Hello2: invokevirtual #65                 // Method java/lang/String.length:()I5: pop6: returnLineNumberTable:line 31: 0line 32: 6LocalVariableTable:Start  Length  Slot  Name   Signature0       7     0  this   Lcom/schlimm/bytecode/examples/BytecodeExamples;
}

上面的字节码片段显示了java.lang的invokevirtual方法调用。 第20行中的String- > length() 。它引用了contsant池表中的Item 65,它是MethodRef条目(请参见第6行)。 常量池表中的项目42和66引用类和方法描述符条目。 如您所见,invokevirtual调用的目标类型和方法已完全解析,并硬连接到字节码中。 现在,让我们回到invokedynamic

重要的是要注意,不可能将Java代码编译为包含invokedynamic指令的字节码。 Java是静态类型的 。 这意味着Java在编译时执行类型检查。 因此,在Java中,有可能(并且想要!)将方法调用接收者的所有类型信息硬连线到调用者类文件中。 调用方知道调用目标的类型名称,如上面的示例所示。 另一方面,使用invokedynamic可使JVM在运行时准确解析该类型信息。 只有动态语言(例如JRuby或Rhino)才需要(也想要!)。

现在,假设您想在动态键入的JVM上实现一种新语言。 我不建议您在JVM上发明另一种语言,但是假设您应该,并且假设您的新语言应被动态键入。 用您的新语言,这意味着在运行时执行方法调用的调用方和接收方之间的链接。 由于Java 7,这可以使用invokedynamic指令在字节码级别上实现。

因为无法使用Java编译器创建invokedynamic指令,所以我将创建一个包含我自己的invokedynamic的类文件。 创建此类文件后,我将使用普通的Java启动器运行该类文件的main方法。 没有编译器,如何创建类文件? 这可以通过使用字节码操作框架(例如ASM或Javassist)来实现 。

下面的代码片段显示了SimpleDynamicInvokerGenerator ,该生成器可以生成一个类文件SimpleDynamicInvoker.class,该文件包含一个invokedynamic指令。

public abstract class AbstractDynamicInvokerGenerator implements Opcodes {public byte[] dump(String dynamicInvokerClassName, String dynamicLinkageClassName, String bootstrapMethodName, String targetMethodDescriptor)throws Exception {ClassWriter cw = new ClassWriter(0);FieldVisitor fv;MethodVisitor mv;AnnotationVisitor av0;cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, dynamicInvokerClassName, null, "java/lang/Object", null);{mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);mv.visitCode();mv.visitVarInsn(ALOAD, 0);mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");mv.visitInsn(RETURN);mv.visitMaxs(1, 1);mv.visitEnd();}{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, dynamicLinkageClassName, bootstrapMethodName,mt.toMethodDescriptorString());int maxStackSize = addMethodParameters(mv);mv.visitInvokeDynamicInsn("runCalculation", targetMethodDescriptor, bootstrap);mv.visitInsn(RETURN);mv.visitMaxs(maxStackSize, 1);mv.visitEnd();}cw.visitEnd();return cw.toByteArray();}protected abstract int addMethodParameters(MethodVisitor mv);}public class SimpleDynamicInvokerGenerator extends AbstractDynamicInvokerGenerator {@Overrideprotected int addMethodParameters(MethodVisitor mv) {return 0;}public static void main(String[] args) throws IOException, Exception {String dynamicInvokerClassName = "com/schlimm/bytecode/SimpleDynamicInvoker";FileOutputStream fos = new FileOutputStream(new File("target/classes/" + dynamicInvokerClassName + ".class"));fos.write(new SimpleDynamicInvokerGenerator().dump(dynamicInvokerClassName, "com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample", "bootstrapDynamic", "()V"));}}

我在这里使用ASM (一种通用的Java字节码操作和分析框架)来完成创建正确的类文件格式的工作。 在第30行中, visitInvokeDynamicInsn创建了invokedynamic指令。 生成一个进行invokedynamic调用的类只是故事的一半。 您还需要一些将动态调用站点链接到实际目标的代码,这是invokedynamic的真正目的。 这是一个例子。

public class SimpleDynamicLinkageExample {private static MethodHandle sayHello;private static void sayHello() {System.out.println("There we go!");}public static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {MethodHandles.Lookup lookup = MethodHandles.lookup();Class thisClass = lookup.lookupClass(); // (who am I?)sayHello = lookup.findStatic(thisClass, "sayHello", MethodType.methodType(void.class));return new ConstantCallSite(sayHello.asType(type));}}

第9-14行中的bootstrap方法选择动态调用的实际目标。 在我们的例子中,目标是sayHello ()方法。 要了解bootstrap方法如何链接到invokedynamic指令,我们需要深入研究使用SimpleDynamicInvokerGenerator生成的SimpleDynamicInvoker字节码。

E:\dev_home\repositories\git\playground\bytecode-playground\target\classes\com\schlimm\bytecode>javap -c -verbose SimpleDynamicInvoker.classClassfile /E:/dev_home/repositories/git/playground/bytecode-playground/target/classes/com/schlimm/bytecode/SimpleDynamicInvoker.classLast modified 30.01.2012; size 512 bytesMD5 checksum 401a0604146e2e95f9563e7d9f9d861b
public class com.schlimm.bytecode.SimpleDynamicInvokerBootstrapMethods:0: #17 invokestatic com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;Method arguments:minor version: 0major version: 51flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Utf8               com/schlimm/bytecode/SimpleDynamicInvoker#2 = Class              #1             //  com/schlimm/bytecode/SimpleDynamicInvoker#3 = Utf8               java/lang/Object#4 = Class              #3             //  java/lang/Object#5 = Utf8               <init>#6 = Utf8               ()V#7 = NameAndType        #5:#6          //  "<init>":()V#8 = Methodref          #4.#7          //  java/lang/Object."<init>":()V#9 = Utf8               main#10 = Utf8               ([Ljava/lang/String;)V#11 = Utf8               com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample#12 = Class              #11            //  com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample#13 = Utf8               bootstrapDynamic#14 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#15 = NameAndType        #13:#14        //  bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#16 = Methodref          #12.#15        //  com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#17 = MethodHandle       #6:#16         //  invokestatic com/schlimm/bytecode/invokedynamic/linkageclasses/SimpleDynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#18 = Utf8               runCalculation#19 = NameAndType        #18:#6         //  runCalculation:()V#20 = InvokeDynamic      #0:#19         //  #0:runCalculation:()V#21 = Utf8               Code#22 = Utf8               BootstrapMethods
{public com.schlimm.bytecode.SimpleDynamicInvoker();flags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #8                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);flags: ACC_PUBLIC, ACC_STATICCode:stack=0, locals=1, args_size=10: invokedynamic #20,  0             // InvokeDynamic #0:runCalculation:()V5: return
}

在第49行中,您可以看到invokedynamic指令。 动态方法的逻辑名称是runCalculation ,这是一个虚拟名称。 您可以使用任何有意义的名称,也可以使用“ +”之类的名称。 该指令引用了竞争池表中的第20项(请参见第33行)。 这又引用了BootstrapMethods属性中的索引0(请参见第8行)。 在这里,您可以看到指向SimpleDynamicLinkageExample.bootstrapDynamic方法的链接,该方法将invokedynamic指令链接到调用目标。

现在,如果您使用java启动器调用SimpleDynamicInvoker ,则将执行invokedynamic调用。

下面的序列图说明了使用Java启动器调用SimpleDynamicInvoker时发生的情况。

使用invokedynamic的runCalculation的第一次调用会发出对bootstrapDynamic方法的调用。 此方法在调用类(SimpleDynamicInvoker)和接收类( SimpleDynamicLinkageExample )之间进行动态链接。 bootstrap方法返回一个以接收类为目标的MethodHandle。 缓存此方法句柄以重复调用runCalculation方法。

这就是invokedynamic。 我在Git仓库中发布了一些更复杂的示例。 我希望您在阅读不足时喜欢阅读本文!

干杯,尼古拉斯

参考:

  • JCG合作伙伴提供的 “ Java 7:一个完整​​的invokedynamic示例”   尼克拉斯。
  • http://docs.oracle.com/javase/7/docs/technotes/guides/vm/multiple-language-support.html
  • http://asm.ow2.org/
  • http://java.sun.com/developer/technicalArticles/DynTypeLang/
  • http://asm.ow2.org/doc/tutorial-asm-2.0.html
  • http://weblogs.java.net/blog/forax/archive/2011/01/07/calling-invokedynamic-java
  • http://nerds-central.blogspot.com/2011/05/performing-dynamicinvoke-from-java-step.html

翻译自: https://www.javacodegeeks.com/2012/02/java-7-complete-invokedynamic-example.html

java自建ocr完整示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357280.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java从入门到天黑|05】JavaSE入门之面向对象(下)

修饰符 1、static修饰符 1、static变量 在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。 静态变量和非静态变量的区别 静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问. 1 public class Student{…

机电传动控制大作业 第一阶段

机电传动控制大作业 第一阶段 一&#xff0e;系统硬件接口定义1.电梯内操作界面: 标有1-7数字的按钮&#xff08;每个按钮有一个LED灯&#xff0c;按下按钮灯即亮&#xff09;,开门&#xff0c;关门以及紧急报警的按钮和楼层指示的LED数码管。电梯门的打开和关闭需要两个行程开…

对后台返回的数据进行评分排序、时间排序!

导读:对后台返回的数据进行评分排序,时间排序,可以倒序,可以正序。 按照评分排序 正序 qualityScoreSort(){this.tableData0.sort((a, b) => {return b.qualityScore - a

@Deprecated新外观可能是什么?

JDK增强建议 &#xff08;JEP&#xff09;277&#xff08;“ 增强的弃用 ”&#xff09;建议“重新定义弃用注释&#xff0c;并提供工具来增强功能生命周期的尾端。” 当前 java.lang.Deprecated的一些限制使我困扰了一段时间。 我特别希望能够使用Deprecated提供文本&#xff…

C++反汇编书

1、 《C反汇编与逆向分析技术揭秘》 2、 转载于:https://www.cnblogs.com/cppskill/p/5459867.html

前端工程师直线学习路径

想自学前端?却不知道学习路径。报个班吧,又怕被坑。一张学习前端路径是带你少走N条弯路。最近两年,前端技术和三大框架地位趋于稳定,推荐这个前端开发学习路径。 新手自学前端的五大阶段。 第一阶段 想成为一名前端开发人员,第一步就是网页布局和效果实现。这时候你需要学…

第三章 SQL

SQL最早版本是由IBM开发的&#xff0c;最初叫做Sequel。20世纪70年代早期是作为System R项目的一部分。 3.1 SQL查询语言概览 数据定义语言数据操纵语言完整性视图定义事务控制嵌入式SQL和动态SQL授权3.2 SQL数据定义 3.2.1 基本类型 char(n)&#xff1a;固定长度varchar(n)&am…

VS code常用插件推荐(总结整理篇)

简介 vscode是微软开发的的一款代码编辑器,就如官网上说的一样,vscode重新定义(redefined)了代码编辑器。当前市面上常用的轻型代码编辑器主要是:sublime,notepad++,editplus,atom这几种。比起notepad++、editplus,vscode集成了许多IDE才具有的功能,比起它们更像一个…

appengine_Google Appengine登台服务器操作方法

appengineGoogle的App Engine开箱即用&#xff0c;支持版本化部署。 您可以非常轻松地在各修订版之间来回切换&#xff0c;这是在上线之前正确测试应用程序的一项很棒的功能。 有一个主要问题&#xff1a;应用程序的所有版本共享同一数据存储。 因此&#xff0c;如果要迁移数据…

Python全栈开发之3、数据类型set补充、深浅拷贝与函数

转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5466082.html 一、基本数据类型补充 set是一个无序而且不重复的集合&#xff0c;有些类似于数学中的集合&#xff0c;也可以求交集&#xff0c;求并集等&#xff0c;下面从代码里来看一下set的用法,如果对这些用法不太熟悉的话…

拿着5家offer的Java,对面试官做了什么?

大家好&#xff0c;我是孙叫兽。本期分享内容从Java初级开始说起&#xff0c;来讲一下要想拿到offer&#xff0c;你必须要做哪些充足准备&#xff01; 先从初级Java开始&#xff0c;当你还是一个初级Java的时候&#xff0c;要想拿到offer&#xff0c;首先要关注自己的简历&…

Spring综合课程总结

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中&#xff0c;向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来&#xff0c;您将深入研究Spring Integration的基础知识&#xff0c;例如通道&#xff0c;转换器和适…

进程与线程的一个简单解释

进程&#xff08;process&#xff09;和线程&#xff08;thread&#xff09;是操作系统的基本概念&#xff0c;但是它们比较抽象&#xff0c;不容易掌握。 最近&#xff0c;我读到一篇材料&#xff0c;发现有一个很好的类比&#xff0c;可以把它们解释地清晰易懂。 1. 计算机的…

1003 阶乘后面0的数量

1003 阶乘后面0的数量 基准时间限制&#xff1a;1 秒 空间限制&#xff1a;131072 KBn的阶乘后面有多少个0&#xff1f; 6的阶乘 1*2*3*4*5*6 720&#xff0c;720后面有1个0。Input一个数N(1 < N < 10^9) Output输出0的数量 Input示例5 Output示例1 //统计2和5个数就好…

《HarmonyOS实战——前端开发华为鸿蒙系统应用 OpenHarmony JS》

《HarmonyOS实战——前端开发华为鸿蒙系统应用 OpenHarmony JS》

(转)数组循环右移

设计一个算法&#xff0c;把一个含有N个元素的数组循环右移K位&#xff0c;要求时间复杂度为O&#xff08;N&#xff09;&#xff0c;且只允许使用两个附加变量。 不合题意的解法如下&#xff1a; 我们先试验简单的办法&#xff0c;可以每次将数组中的元素右移一位&#xff0c;…

Redis命令–使用Redis命令行

本文是我们学院课程的一部分&#xff0c;标题为Redis NoSQL键值存储 。 这是Redis的速成班。 您将学习如何安装Redis并启动服务器。 此外&#xff0c;您将在Redis命令行中乱七八糟。 接下来是更高级的主题&#xff0c;例如复制&#xff0c;分片和集群&#xff0c;同时还介绍了…

前端面试官常问javaScript编程题,隔壁王大爷看了都会了

目录 1.数组排序。 2.数组元素的去重&#xff1b; 3.用递归的方法求数组的求和&#xff1b; 4.防抖节流的思路。 5.深拷贝、浅拷贝&#xff1b; 6.做一个10秒的倒计时&#xff1b; 7.setTimeout()和setInterval()的使用以及区别 导读&#xff1a;一些常见的前端面试官会让…

(五)Struts2 标签

所有的学习我们必须先搭建好Struts2的环境&#xff08;1、导入对应的jar包&#xff0c;2、web.xml&#xff0c;3、struts.xml&#xff09; 第一节&#xff1a;Struts2 标签简介 Struts2 自己封装了一套标签&#xff0c;比JSTL 强大&#xff0c;而且与Struts2 中的其他功能无缝结…

HarmonyOS常见问题解答

学习资源主要分享 一、解答学习者的担心:手机/生态设备数量 、应用数量