一、前言
几年前,接到一个开发任务:用Java开发能运行Java智能合约的虚拟机。在开发Java智能合约时,只能使用智能合约SDK提供的类和一些Java常用类(8种基本数据类型包装类;String、BigInteger、BigDecimal、List、Map、Set 相关的类)。
完整的Java智能合约虚拟机比较复杂,且要保存Java智能合约状态。 这篇文章仅介绍一个简单JVM实现,支持少量字节码。 参考 Java 虚拟机规范(Java SE 8),里面写到:要正确实现 Java 虚拟机,只需能够读取class文件格式并正确执行其中指定的操作。为了简化实现,使用了 ASM解析class文件 。
二、使用ASM解析class文件
使用 ASM Tree API 解析class文件,获得一个 ClassNode 对象,里面包含 class 文件的各种信息。要运行class定义的方法,先在ClassNode中找到这个方法(MethodNode包含方法的各种信息),然后执行方法的指令集。MethodNode.instructions 是这个方法的指令集,遍历指令集,执行每个指令,只要正确执行了指令,方法就能完成运行。
三、实现JVM运行时数据区
要正确执行指令,先要了解JVM结构,参考 Java虚拟机规范第二章(JVM结构),里面介绍了JVM运行时数据区,定义了在程序执行期间使用的各种运行时数据区,如图所示:
下面简要介绍各种运行时数据区,详细信息查看 Java虚拟机规范第二章(JVM结构),根据这些信息,可以简单实现各种运行时数据区。
3.1 程序计数器
Java 虚拟机可以同时支持多个执行线程。每个线程都有自己的程序计数器。程序计数器包含当前线程正在执行的 Java 虚拟机指令的地址。
程序计数器最主要作用就是包含当前指令,程序计数器简单实现如下: