
案例介绍
本章主要介绍如何实现让虚拟机处理数组和字符串,在虚拟机功能增强后,我们可以执行数组类型计算和输出字符串。本章需要新增实现数组指令;newarray、anewarray、arraylength、aload、astore、multianewarray、ldc,同时需要需要开发字符串池方法等。
数组在Java虚拟机中是给比较特殊的概念,主要有以下原因;
首先,数组类和普通的类是不同的。普通的类从class文件中加载,但是数组类由Java虚拟机在运行时生成。数组的类名是左括号([)+数组元素的类型描述符;数组的类型描述符就是类名本身。例如,int[]的类名是[I,int[][]的类名是[[I,Object[]的类名是[Ljava/lang/Object;,String[][]的类名是[[java/lang/String;,等等。
其次,创建数组的方式和创建普通对象的方式不同。普通对象new指令创建,然后由构造函数初始化。基本类型数组由newarray指令创建;引用类型数组由anewarray指令创建;另外还有一个专门的mulitianewarray指令用于创建多维数组。
最后,很显然,数组和普通对象存在的数据也是不同的。普通对象中存放的是实例变量,通过putfield和getfield指令存取。数组对象中存放的则是数组元素,通过aload和astore系列指令按索引存取。其中可以是a、b、c、d、f、i、l或者s,分别用于存取引用、byte、char、double、float、int、long或者shore类型的数组。另外,还有一个arraylength指令,用于获取数组长度。
环境准备
1、jdk 1.8.0
2、IntelliJ IDEA Community Edition 2018.3.1 x64
配置信息
1、调试配置
2.1、配置位置:Run/Debug Configurations -> program arguments
2.2、配置内容(执行数组计算):-Xjre “C:Program FilesJavajdk1.8.0_161jre” E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-08targettest-classesorgitstackdemotestBubbleSortTest
2.2、配置内容(字符串的输出):-Xjre “C:Program FilesJavajdk1.8.0_161jre” E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-08targettest-classesorgitstackdemotestHelloWorld -verbose true -args 你好,java版虚拟机v1.0,欢迎你的到来。
代码示例
itstack-demo-jvm-08
├── pom.xml
└── src└── main│    └── java│        └── org.itstack.demo.jvm│             ├── classfile│             │   ├── attributes   {BootstrapMethods/Code/ConstantValue...}│             │   ├── constantpool {CONSTANT_TAG_CLASS/CONSTANT_TAG_FIELDREF/CONSTANT_TAG_METHODREF...}│             │   ├── ClassFile.java│             │   ├── ClassReader.java│             │   └── MemberInfo.java   │             ├── classpath│             │   ├── impl│             │   │   ├── CompositeEntry.java│             │   │   ├── DirEntry.java │             │   │   ├── WildcardEntry.java │             │   │   └── ZipEntry.java    │             │   ├── Classpath.java│             │   └── Entry.java   │             ├── classpath│             │   ├── base│             │   │   ├── BytecodeReader.java│             │   │   ├── ClassInitLogic.java│             │   │   ├── Instruction.java│             │   │   ├── InstructionBranch.java│             │   │   ├── InstructionIndex8.java│             │   │   ├── InstructionIndex16.java│             │   │   ├── InstructionNoOperands.java	│             │   │   └── MethodInvokeLogic.java│             │   ├── comparisons│             │   ├── constants│             │   ├── control│             │   ├── conversions│             │   ├── extended│             │   ├── loads│             │   ├── math│             │   ├── references│             │   │   ├── ANEW_ARRAY.java│             │   │   ├── ARRAY_LENGTH.java│             │   │   ├── CHECK_CAST.java│             │   │   ├── GET_FIELD.java│             │   │   ├── GET_STATIC.java│             │   │   ├── INSTANCE_OF.java│             │   │   ├── INVOKE_INTERFACE.java│             │   │   ├── INVOKE_SPECIAL.java│             │   │   ├── INVOKE_STATIC.java│             │   │   ├── INVOKE_VIRTUAL.java│             │   │   ├── MULTI_ANEW_ARRAY.java│             │   │   ├── NEW.java│             │   │   ├── NEW_ARRAY.java│             │   │   ├── PUT_FIELD.java│             │   │   └── PUT_STATIC.java│             │   ├── stack│             │   ├── store│             │   │   └── xastore│             │   │       ├── AASTORE.java	│             │   │       ├── BASTORE.java	│             │   │       ├── CASTORE.java	│             │   │       ├── DASTORE.java│             │   │       ├── FASTORE.java│             │   │       ├── IASTORE.java│             │   │       ├── LASTORE.java	│             │   │       └── SASTORE.java		│             │   └── Factory   │             ├── rtda│             │   ├── heap│             │   │   ├── constantpool│             │   │   ├── methodarea│             │   │   │   ├── Class.java    │             │   │   │   ├── ClassMember.java  │             │   │   │   ├── Field.java    │             │   │   │   ├── Method.java │             │   │   │   ├── MethodDescriptor.java │             │   │   │   ├── MethodDescriptorParser.java │             │   │   │   ├── MethodLookup.java 	│             │   │   │   ├── Object.java   │             │   │   │   ├── Slots.java   │             │   │   │   └── StringPool.java	│             │   │   └── ClassLoader.java  │             │   ├── Frame.java│             │   ├── JvmStack.java│             │   ├── LocalVars.java│             │   ├── OperandStack.java│             │   ├── Slot.java │             │   └── Thread.java│             ├── Cmd.java│             ├── Interpret.java    │             └── Main.java└── test└── java└── org.itstack.demo.test├── BubbleSortTest.java└── HelloWorld.java代码片段
ANEW_ARRAY.java
package org.itstack.demo.jvm.instructions.references;import org.itstack.demo.jvm.instructions.base.InstructionIndex16;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.OperandStack;
import org.itstack.demo.jvm.rtda.heap.constantpool.ClassRef;
import org.itstack.demo.jvm.rtda.heap.constantpool.RunTimeConstantPool;
import org.itstack.demo.jvm.rtda.heap.methodarea.Class;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;/*** http://www.itstack.org* create by fuzhengwei on 2019/4/29* create new array of reference*/
public class ANEW_ARRAY extends InstructionIndex16 {@Overridepublic void execute(Frame frame) {RunTimeConstantPool runTimeConstantPool = frame.method().clazz().constantPool();ClassRef classRef = (ClassRef) runTimeConstantPool.getConstants(this.idx);Class componentClass = classRef.resolvedClass();OperandStack stack = frame.operandStack();int count = stack.popInt();if (count < 0) {throw new NegativeArraySizeException();}Class arrClass = componentClass.arrayClass();Object arr = arrClass.newArray(count);stack.pushRef(arr);}}ARRAY_LENGTH.java
package org.itstack.demo.jvm.instructions.references;import org.itstack.demo.jvm.instructions.base.InstructionNoOperands;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.OperandStack;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;/*** http://www.itstack.org* create by fuzhengwei on 2019/4/29* get length of array*/
public class ARRAY_LENGTH extends InstructionNoOperands {@Overridepublic void execute(Frame frame) {OperandStack stack = frame.operandStack();Object arrRef = stack.popRef();if (null == arrRef){throw new NullPointerException();}int arrLen = arrRef.arrayLength();stack.pushInt(arrLen);}}NEW_ARRAY.java
package org.itstack.demo.jvm.instructions.references;import org.itstack.demo.jvm.instructions.base.BytecodeReader;
import org.itstack.demo.jvm.instructions.base.Instruction;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.OperandStack;
import org.itstack.demo.jvm.rtda.heap.ClassLoader;
import org.itstack.demo.jvm.rtda.heap.methodarea.Class;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;/*** http://www.itstack.org* create by fuzhengwei on 2019/4/29*/
public class NEW_ARRAY implements Instruction {private byte atype;@Overridepublic void fetchOperands(BytecodeReader reader) {this.atype = reader.readByte();}@Overridepublic void execute(Frame frame) {OperandStack stack = frame.operandStack();int count = stack.popInt();if (count < 0) {throw new NegativeArraySizeException();}ClassLoader classLoader = frame.method().clazz().loader();Class arrClass = getPrimitiveArrayClass(classLoader, this.atype);Object arr = arrClass.newArray(count);stack.pushRef(arr);}private Class getPrimitiveArrayClass(ClassLoader loader, byte atype){switch (atype) {case ArrayType.AT_BOOLEAN:return loader.loadClass("[Z");case ArrayType.AT_BYTE:return loader.loadClass("[B");case ArrayType.AT_CHAR:return loader.loadClass("[C");case ArrayType.AT_SHORT:return loader.loadClass("[S");case ArrayType.AT_INT:return loader.loadClass("[I");case ArrayType.AT_LONG:return loader.loadClass("[J");case ArrayType.AT_FLOAT:return loader.loadClass("[F");case ArrayType.AT_DOUBLE:return loader.loadClass("[D");default:throw new RuntimeException("Invalid atype!");}}static class ArrayType {static final byte AT_BOOLEAN = 4;static final byte AT_CHAR = 5;static final byte AT_FLOAT = 6;static final byte AT_DOUBLE = 7;static final byte AT_BYTE = 8;static final byte AT_SHORT = 9;static final byte AT_INT = 10;static final byte AT_LONG = 11;}}
IASTORE.java
package org.itstack.demo.jvm.instructions.stores.xastore;import org.itstack.demo.jvm.instructions.base.InstructionNoOperands;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.OperandStack;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;/*** http://www.itstack.org* create by fuzhengwei on 2019/4/29*/
public class IASTORE extends InstructionNoOperands {@Overridepublic void execute(Frame frame) {OperandStack stack = frame.operandStack();int val = stack.popInt();int idx = stack.popInt();Object arrRef = stack.popRef();checkNotNull(arrRef);int[] ints = arrRef.ints();checkIndex(ints.length, idx);ints[idx] = val;}}StringPool.java
package org.itstack.demo.jvm.rtda.heap.methodarea;import org.itstack.demo.jvm.rtda.heap.ClassLoader;import java.util.HashMap;
import java.util.Map;/*** http://www.itstack.org* create by fuzhengwei on 2019/4/29*/
public class StringPool {private static Map<String, Object> internedStrs = new HashMap<>();public static Object jString(ClassLoader loader, String goStr) {Object internedStr = internedStrs.get(goStr);if (null != internedStr) return internedStr;char[] chars = goStr.toCharArray();Object jChars = new Object(loader.loadClass("[C"), chars);Object jStr = loader.loadClass("java/lang/String").newObject();jStr.setRefVal("value", "[C", jChars);internedStrs.put(goStr, jStr);return jStr;}public static String goString(Object jStr) {Object charArr = jStr.getRefVar("value", "[C");return new String(charArr.chars());}}Interpret.java
package org.itstack.demo.jvm;import com.alibaba.fastjson.JSON;
import org.itstack.demo.jvm.instructions.Factory;
import org.itstack.demo.jvm.instructions.base.BytecodeReader;
import org.itstack.demo.jvm.instructions.base.Instruction;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.Thread;
import org.itstack.demo.jvm.rtda.heap.ClassLoader;
import org.itstack.demo.jvm.rtda.heap.methodarea.*;
import org.itstack.demo.jvm.rtda.heap.methodarea.Class;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;//指令集解释器
class Interpret {Interpret(Method method, boolean logInst, String args) {Thread thread = new Thread();Frame frame = thread.newFrame(method);thread.pushFrame(frame);if (null != args){Object jArgs = createArgsArray(method.clazz().loader(), args.split(" "));frame.localVars().setRef(0, jArgs);}loop(thread, logInst);}private Object createArgsArray(ClassLoader loader, String[] args) {Class stringClass = loader.loadClass("java/lang/String");Object argsArr = stringClass.arrayClass().newArray(args.length);Object[] jArgs = argsArr.refs();for (int i = 0; i < jArgs.length; i++) {jArgs[i] = StringPool.jString(loader, args[i]);}return argsArr;}private void loop(Thread thread, boolean logInst) {BytecodeReader reader = new BytecodeReader();while (true) {Frame frame = thread.currentFrame();int pc = frame.nextPC();thread.setPC(pc);reader.reset(frame.method().code, pc);byte opcode = reader.readByte();Instruction inst = Factory.newInstruction(opcode);if (null == inst) {System.out.println("Unsupported opcode " + byteToHexString(new byte[]{opcode}));break;}inst.fetchOperands(reader);frame.setNextPC(reader.pc());if (logInst) {logInstruction(frame, inst, opcode);}//execinst.execute(frame);if (thread.isStackEmpty()) {break;}}}private static void logInstruction(Frame frame, Instruction inst, byte opcode) {Method method = frame.method();String className = method.clazz().name();String methodName = method.name();String outStr = (className + "." + methodName + "() t") +"寄存器(指令):" + byteToHexString(new byte[]{opcode}) + " -> " + inst.getClass().getSimpleName() + " => 局部变量表:" + 
JSON.toJSONString(frame.operandStack().getSlots()) + " 操作数栈:" + JSON.toJSONString(frame.operandStack().getSlots());System.out.println(outStr);}private static String byteToHexString(byte[] codes) {StringBuilder sb = new StringBuilder();sb.append("0x");for (byte b : codes) {int value = b & 0xFF;String strHex = Integer.toHexString(value);if (strHex.length() < 2) {strHex = "0" + strHex;}sb.append(strHex);}return sb.toString();}}BubbleSortTest.java
package org.itstack.demo.test;/*** -Xjre "C:Program FilesJavajdk1.8.0_161jre" E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-08targettest-classesorgitstackdemotestBubbleSortTest -verbose true*/
public class BubbleSortTest {public static void main(String[] args) {int[] arr = {22, 84, 77, 11, 95,  9, 78, 56, 36, 97, 65, 36, 10, 24 ,92, 48};//printArray(arr);bubbleSort(arr);//System.out.println(123456789);printArray(arr);}private static void bubbleSort(int[] arr) {boolean swapped = true;int j = 0;int tmp;while (swapped) {swapped = false;j++;for (int i = 0; i < arr.length - j; i++) {if (arr[i] > arr[i + 1]) {tmp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = tmp;swapped = true;}}}}private static void printArray(int[] arr) {for (int i : arr) {System.out.println(i);}}}HelloWorld.java
package org.itstack.demo.test;/*** -Xjre "C:Program FilesJavajdk1.8.0_161jre" E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-08targettest-classesorgitstackdemotestHelloWorld -verbose true -args 你好,java版虚拟机v1.0,欢迎你的到来。*/
public class HelloWorld {public static void main(String[] args) {for (String str : args) {System.out.println(str);}}}测试结果一;执行数组
-Xjre "C:Program FilesJavajdk1.8.0_161jre" E:itstackgitistack-demoitstack-demo-jvmitstack-demo-jvm-08targettest-classesorgitstackdemotestBubbleSortTest -verbose true
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":0},{"num":0},{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0xbc -> NEW_ARRAY => 局部变量表:[{"num":16},{"num":0},{"num":0},{"num":0}] 操作数栈:[{"num":16},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":0},{"num":0},{"num":0}] 操作数栈:[{"num":16,"ref":{}},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x03 -> ICONST_0 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":0}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":0}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":0}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":0}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":22}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":22}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":0},{"num":22}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":0},{"num":22}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x04 -> ICONST_1 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":22}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":0},{"num":22}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":22}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":22}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":84}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":84}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":1},{"num":84}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":1},{"num":84}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x05 -> ICONST_2 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":84}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":1},{"num":84}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":84}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":84}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":77}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":77}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":2},{"num":77}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":2},{"num":77}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x06 -> ICONST_3 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":77}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":2},{"num":77}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":77}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":77}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":11}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":11}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":3},{"num":11}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":3},{"num":11}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x07 -> ICONST_4 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":11}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":3},{"num":11}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":11}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":11}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":95}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":95}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":4},{"num":95}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":4},{"num":95}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x08 -> ICONST_5 => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":95}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":4},{"num":95}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":95}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":95}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":9}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":9}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":5},{"num":9}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":5},{"num":9}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":9}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":5},{"num":9}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":9}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":9}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":78}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":78}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":6},{"num":78}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":6},{"num":78}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":78}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":6},{"num":78}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":78}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":78}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":56}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":56}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":7},{"num":56}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":7},{"num":56}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":56}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":7},{"num":56}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":56}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":56}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":8},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":8},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":8},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":97}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":97}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":9},{"num":97}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":9},{"num":97}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":97}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":9},{"num":97}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":97}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":97}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":65}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":65}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":10},{"num":65}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":10},{"num":65}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":65}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":10},{"num":65}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":65}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":65}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":11},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":11},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":11},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":36}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":36}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":10}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":10}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":12},{"num":10}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":12},{"num":10}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":10}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":12},{"num":10}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":10}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":10}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":24}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":24}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":13},{"num":24}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":13},{"num":24}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":24}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":13},{"num":24}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":24}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":24}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":92}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":92}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x59 -> DUP => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":14},{"num":92}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":14},{"num":92}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":92}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":14},{"num":92}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":15},{"num":92}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":15},{"num":92}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4f -> IASTORE => 局部变量表:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":15},{"num":48}] 操作数栈:[{"num":16,"ref":{}},{"num":16,"ref":{"$ref":"$[0].ref"}},{"num":15},{"num":48}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x4c -> ASTORE_1 => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0x2b -> ALOAD_1 => 局部变量表:[{"num":16},{"num":16},{"num":15},{"num":48}] 操作数栈:[{"num":16},{"num":16},{"num":15},{"num":48}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0xb8 -> INVOKE_STATIC => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}]
java/lang/Object.<clinit>() 	寄存器(指令):0xb8 -> INVOKE_STATIC => 局部变量表:null 操作数栈:null
java/lang/Object.<clinit>() 	寄存器(指令):0xb1 -> RETURN => 局部变量表:null 操作数栈:null
... ...
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xb2 -> GET_STATIC => 局部变量表:[{"num":9},{"num":0}] 操作数栈:[{"num":9},{"num":0}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x15 -> ILOAD => 局部变量表:[{"num":9},{"num":0}] 操作数栈:[{"num":9},{"num":0}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xb6 -> INVOKE_VIRTUAL => 局部变量表:[{"num":9},{"num":9}] 操作数栈:[{"num":9},{"num":9}]
9
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x84 -> IINC => 局部变量表:[{"num":9},{"num":9}] 操作数栈:[{"num":9},{"num":9}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xa7 -> GOTO => 局部变量表:[{"num":9},{"num":9}] 操作数栈:[{"num":9},{"num":9}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x1d -> ILOAD_3 => 局部变量表:[{"num":9},{"num":9}] 操作数栈:[{"num":9},{"num":9}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":1},{"num":9}] 操作数栈:[{"num":1},{"num":9}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xa2 -> IF_ICMPGE => 局部变量表:[{"num":1},{"num":16}] 操作数栈:[{"num":1},{"num":16}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x2b -> ALOAD_1 => 局部变量表:[{"num":1},{"num":16}] 操作数栈:[{"num":1},{"num":16}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x1d -> ILOAD_3 => 局部变量表:[{"num":1,"ref":{}},{"num":16}] 操作数栈:[{"num":1,"ref":{}},{"num":16}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x2e -> IALOAD => 局部变量表:[{"num":1,"ref":{}},{"num":1}] 操作数栈:[{"num":1,"ref":{}},{"num":1}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x36 -> ISTORE => 局部变量表:[{"num":10},{"num":1}] 操作数栈:[{"num":10},{"num":1}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xb2 -> GET_STATIC => 局部变量表:[{"num":10},{"num":1}] 操作数栈:[{"num":10},{"num":1}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x15 -> ILOAD => 局部变量表:[{"num":10},{"num":1}] 操作数栈:[{"num":10},{"num":1}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xb6 -> INVOKE_VIRTUAL => 局部变量表:[{"num":10},{"num":10}] 操作数栈:[{"num":10},{"num":10}]
10
11
22
24
36
36
48
56
65
77
78
84
92
95
97
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x84 -> IINC => 局部变量表:[{"num":97},{"num":97}] 操作数栈:[{"num":97},{"num":97}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xa7 -> GOTO => 局部变量表:[{"num":97},{"num":97}] 操作数栈:[{"num":97},{"num":97}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x1d -> ILOAD_3 => 局部变量表:[{"num":97},{"num":97}] 操作数栈:[{"num":97},{"num":97}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":16},{"num":97}] 操作数栈:[{"num":16},{"num":97}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xa2 -> IF_ICMPGE => 局部变量表:[{"num":16},{"num":16}] 操作数栈:[{"num":16},{"num":16}]
org/itstack/demo/test/BubbleSortTest.printArray() 	寄存器(指令):0xb1 -> RETURN => 局部变量表:[{"num":16},{"num":16}] 操作数栈:[{"num":16},{"num":16}]
org/itstack/demo/test/BubbleSortTest.main() 	寄存器(指令):0xb1 -> RETURN => 局部变量表:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}] 操作数栈:[{"num":16,"ref":{}},{"num":16},{"num":15},{"num":48}]Process finished with exit code 0原作者:付政委
原文链接:用Java实现JVM第八章《数组和字符串》
原出处:付政委的博客
