本章節主要用java實現;方法調用指令、返回指令、解析方法符號引用、參數傳遞等。實現新的指令後咱們的虛擬機就能夠執行稍微複雜的運算並輸出結果。html
從調用的角度來看,方法能夠分爲兩類:靜態方法(或者類方法)和實例方法。靜態方法經過類類調用,實例方法則經過對象引用來調用。靜態方法是靜態綁定的,也就是說,最終調用的是哪給方法在編譯期就已經肯定。實例方法則支持動態綁定,最終要調用哪給方法可能要推遲到運行期才能知道。java
從實現的角度來看,方法能夠分爲三類:沒有實現(也就是抽象方法)、用Java語言(或者JVM上其餘的語言,如Groovy和Scala等)實現和用本地語言(如C或者C++)實現。靜態方法和抽象方法是互斥的。在Java 8以前,接口只能包括抽象方法。爲了實現Lambda表達式,Java 8放寬了這一限制,在接口中也能夠定義靜態方法和默認方法。git
在Java 7以前,Java虛擬機規範一共提供了4條方法調用指令。其中invokestatic指令用來調用靜態方法。invokespecial指令用來調用無須動態綁定的實例方法,包括構造函數、私有方法和經過super關鍵字調用的超類方法。剩下的狀況則屬於動態綁定。若是是針對接口類型的引用調用方法,就使用invokeinterface指令,不然使用invokevirtual指令。數組
itstack-demo-jvm-07
├── 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
│ │ │ ├── CHECK_CAST.java
│ │ │ ├── GET_FIELD.java
│ │ │ ├── GET_STATIC.java
│ │ │ ├── INSTANCE_OF.java
│ │ │ ├── INVOKE_INTERFACE.java
│ │ │ ├── INVOKE_SPECIAL.java
│ │ │ ├── INVOKE_STATIC.java
│ │ │ ├── INVOKE_VIRTUAL.java
│ │ │ ├── NEW.java
│ │ │ ├── PUT_FIELD.java
│ │ │ └── PUT_STATIC.java
│ │ ├── stack
│ │ ├── store
│ │ └── Factory
│ ├── rtda
│ │ ├── heap
│ │ │ ├── constantpool
│ │ │ ├── methodarea
│ │ │ │ ├── Class.java
│ │ │ │ ├── ClassMember.java
│ │ │ │ ├── Field.java
│ │ │ │ ├── Method.java
│ │ │ │ ├── MethodDescriptor.java
│ │ │ │ ├── MethodDescriptorParser.java
│ │ │ │ ├── MethodLookup.java
│ │ │ │ ├── Object.java
│ │ │ │ └── Slots.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
└── HelloWorld.java
複製代碼
代碼篇幅較長,只列重點代碼塊微信
MethodInvokeLogic.javaapp
package org.itstack.demo.jvm.instructions.base;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.Slot;
import org.itstack.demo.jvm.rtda.Thread;
import org.itstack.demo.jvm.rtda.heap.methodarea.Method;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class MethodInvokeLogic {
public static void invokeMethod(Frame invokerFrame, Method method) {
Thread thread = invokerFrame.thread();
Frame newFrame = thread.newFrame(method);
thread.pushFrame(newFrame);
int argSlotCount = method.argSlotCount();
if (argSlotCount > 0) {
for (int i = argSlotCount - 1; i >= 0; i--) {
Slot slot = invokerFrame.operandStack().popSlot();
newFrame.localVars().setSlot(i, slot);
}
}
//hack
if (method.isNative()) {
if ("registerNatives".equals(method.name())) {
thread.popFrame();
} else {
throw new RuntimeException("native method " + method.name());
}
}
}
}
複製代碼
INVOKE_INTERFACE.javajvm
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.instructions.base.MethodInvokeLogic;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.heap.constantpool.InterfaceMethodRef;
import org.itstack.demo.jvm.rtda.heap.constantpool.RunTimeConstantPool;
import org.itstack.demo.jvm.rtda.heap.methodarea.Method;
import org.itstack.demo.jvm.rtda.heap.methodarea.MethodLookup;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class INVOKE_INTERFACE implements Instruction {
private int idx;
@Override
public void fetchOperands(BytecodeReader reader) {
this.idx = reader.readShort();
reader.readByte();
reader.readByte();
}
@Override
public void execute(Frame frame) {
RunTimeConstantPool runTimeConstantPool = frame.method().clazz().constantPool();
InterfaceMethodRef methodRef = (InterfaceMethodRef) runTimeConstantPool.getConstants(this.idx);
Method resolvedMethod = methodRef.resolvedInterfaceMethod();
if (resolvedMethod.isStatic() || resolvedMethod.isPrivate()) {
throw new IncompatibleClassChangeError();
}
Object ref = frame.operandStack().getRefFromTop(resolvedMethod.argSlotCount() - 1);
if (null == ref) {
throw new NullPointerException();
}
if (!ref.clazz().isImplements(methodRef.resolvedClass())) {
throw new IncompatibleClassChangeError();
}
Method methodToBeInvoked = MethodLookup.lookupMethodInClass(ref.clazz(), methodRef.name(), methodRef.descriptor());
if (null == methodToBeInvoked || methodToBeInvoked.isAbstract()) {
throw new AbstractMethodError();
}
if (!methodToBeInvoked.isPublic()) {
throw new IllegalAccessError();
}
MethodInvokeLogic.invokeMethod(frame, methodToBeInvoked);
}
}
複製代碼
INVOKE_SPECIAL.javaide
package org.itstack.demo.jvm.instructions.references;
import org.itstack.demo.jvm.instructions.base.InstructionIndex16;
import org.itstack.demo.jvm.instructions.base.MethodInvokeLogic;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.heap.constantpool.MethodRef;
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.Method;
import org.itstack.demo.jvm.rtda.heap.methodarea.MethodLookup;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;
public class INVOKE_SPECIAL extends InstructionIndex16 {
@Override
public void execute(Frame frame) {
Class currentClass = frame.method().clazz();
RunTimeConstantPool runTimeConstantPool = currentClass.constantPool();
MethodRef methodRef = (MethodRef) runTimeConstantPool.getConstants(this.idx);
Class resolvedClass = methodRef.resolvedClass();
Method resolvedMethod = methodRef.ResolvedMethod();
if ("<init>".equals(resolvedMethod.name()) && resolvedMethod.clazz() != resolvedClass) {
throw new NoSuchMethodError();
}
if (resolvedMethod.isStatic()) {
throw new IncompatibleClassChangeError();
}
Object ref = frame.operandStack().getRefFromTop(resolvedMethod.argSlotCount() - 1);
if (null == ref) {
throw new NullPointerException();
}
if (resolvedMethod.isProtected() &&
resolvedMethod.clazz().isSubClassOf(currentClass) &&
!resolvedMethod.clazz().getPackageName().equals(currentClass.getPackageName()) &&
ref.clazz() != currentClass &&
!ref.clazz().isSubClassOf(currentClass)) {
throw new IllegalAccessError();
}
Method methodToBeInvoked = resolvedMethod;
if (currentClass.isSuper() &&
resolvedClass.isSubClassOf(currentClass) &&
!resolvedMethod.name().equals("<init>")) {
MethodLookup.lookupMethodInClass(currentClass.superClass, methodRef.name(), methodRef.descriptor());
}
if (methodToBeInvoked.isAbstract()) {
throw new AbstractMethodError();
}
MethodInvokeLogic.invokeMethod(frame, methodToBeInvoked);
}
}
複製代碼
INVOKE_STATIC.java函數
package org.itstack.demo.jvm.instructions.references;
import org.itstack.demo.jvm.instructions.base.ClassInitLogic;
import org.itstack.demo.jvm.instructions.base.InstructionIndex16;
import org.itstack.demo.jvm.instructions.base.MethodInvokeLogic;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.heap.constantpool.MethodRef;
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.Method;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class INVOKE_STATIC extends InstructionIndex16 {
@Override
public void execute(Frame frame) {
RunTimeConstantPool runTimeConstantPool = frame.method().clazz().constantPool();
MethodRef methodRef = (MethodRef) runTimeConstantPool.getConstants(this.idx);
Method resolvedMethod = methodRef.ResolvedMethod();
if (!resolvedMethod.isStatic()) {
throw new IncompatibleClassChangeError();
}
Class clazz = resolvedMethod.clazz();
if (!clazz.initStarted()) {
frame.revertNextPC();
ClassInitLogic.initClass(frame.thread(), clazz);
return;
}
MethodInvokeLogic.invokeMethod(frame, resolvedMethod);
}
}
複製代碼
INVOKE_VIRTUAL.javaoop
package org.itstack.demo.jvm.instructions.references;
import org.itstack.demo.jvm.instructions.base.InstructionIndex16;
import org.itstack.demo.jvm.instructions.base.MethodInvokeLogic;
import org.itstack.demo.jvm.rtda.Frame;
import org.itstack.demo.jvm.rtda.OperandStack;
import org.itstack.demo.jvm.rtda.heap.constantpool.MethodRef;
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.Method;
import org.itstack.demo.jvm.rtda.heap.methodarea.MethodLookup;
import org.itstack.demo.jvm.rtda.heap.methodarea.Object;
public class INVOKE_VIRTUAL extends InstructionIndex16 {
@Override
public void execute(Frame frame) {
Class currentClass = frame.method().clazz();
RunTimeConstantPool runTimeConstantPool = currentClass.constantPool();
MethodRef methodRef = (MethodRef) runTimeConstantPool.getConstants(this.idx);
Method resolvedMethod = methodRef.ResolvedMethod();
if (resolvedMethod.isStatic()) {
throw new IncompatibleClassChangeError();
}
Object ref = frame.operandStack().getRefFromTop(resolvedMethod.argSlotCount() - 1);
if (null == ref) {
if ("println".equals(methodRef.name())) {
_println(frame.operandStack(), methodRef.descriptor());
return;
}
throw new NullPointerException();
}
if (resolvedMethod.isProtected() &&
resolvedMethod.clazz().isSubClassOf(currentClass) &&
!resolvedMethod.clazz().getPackageName().equals(currentClass.getPackageName()) &&
ref.clazz() != currentClass &&
!ref.clazz().isSubClassOf(currentClass)) {
throw new IllegalAccessError();
}
Method methodToBeInvoked = MethodLookup.lookupMethodInClass(ref.clazz(), methodRef.name(), methodRef.descriptor());
if (null == methodToBeInvoked || methodToBeInvoked.isAbstract()) {
throw new AbstractMethodError();
}
MethodInvokeLogic.invokeMethod(frame, methodToBeInvoked);
}
//hack
private void _println(OperandStack stack, String descriptor) {
switch (descriptor) {
case "(Z)V":
System.out.println(stack.popInt() != 0);
break;
case "(C)V":
System.out.println(stack.popInt());
break;
case "(I)V":
case "(B)V":
case "(S)V":
System.out.println(stack.popInt());
break;
case "(F)V":
System.out.println(stack.popFloat());
break;
case "(J)V":
System.out.println(stack.popLong());
break;
case "(D)V":
System.out.println(stack.popDouble());
break;
default:
System.out.println(descriptor);
break;
}
stack.popRef();
}
}
複製代碼
MethodDescriptor.java
package org.itstack.demo.jvm.rtda.heap.methodarea;
import java.util.ArrayList;
import java.util.List;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class MethodDescriptor {
public List<String> parameterTypes = new ArrayList<>();
public String returnType;
public void addParameterType(String type){
this.parameterTypes.add(type);
}
}
複製代碼
MethodDescriptorParser.java
package org.itstack.demo.jvm.rtda.heap.methodarea;
import javax.management.ObjectName;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class MethodDescriptorParser {
private String raw;
private int offset;
private MethodDescriptor parsed;
public static MethodDescriptor parseMethodDescriptorParser(String descriptor) {
MethodDescriptorParser parser = new MethodDescriptorParser();
return parser.parse(descriptor);
}
public MethodDescriptor parse(String descriptor) {
this.raw = descriptor;
this.parsed = new MethodDescriptor();
this.startParams();
this.parseParamTypes();
this.endParams();
this.parseReturnType();
this.finish();
return this.parsed;
}
private void startParams() {
if (this.readUint8() != '(') {
causePanic();
}
}
private void endParams() {
if (this.readUint8() != ')') {
causePanic();
}
}
public void finish(){
if (this.offset != this.raw.length()){
this.causePanic();
}
}
public void causePanic() {
throw new RuntimeException("BAD descriptor:" + this.raw);
}
public byte readUint8() {
byte[] bytes = this.raw.getBytes();
byte b = bytes[this.offset];
this.offset++;
return b;
}
public void unreadUint8() {
this.offset--;
}
public void parseParamTypes() {
while (true) {
String type = this.parseFieldType();
if ("".equals(type)) break;
this.parsed.addParameterType(type);
}
}
public void parseReturnType() {
if (this.readUint8() == 'V'){
this.parsed.returnType = "V";
return;
}
this.unreadUint8();
String type = this.parseFieldType();
if (!"".equals(type)){
this.parsed.returnType = type;
return;
}
this.causePanic();
}
public String parseFieldType() {
switch (this.readUint8()) {
case 'B':
return "B";
case 'C':
return "C";
case 'D':
return "D";
case 'F':
return "F";
case 'I':
return "I";
case 'J':
return "J";
case 'S':
return "S";
case 'Z':
return "Z";
case 'L':
return this.parseObjectType();
case '[':
return this.parseArrayType();
default:
this.unreadUint8();
return "";
}
}
private String parseObjectType() {
String unread = this.raw.substring(this.offset);
int semicolonIndx = unread.indexOf(";");
if (semicolonIndx == -1) {
this.causePanic();
return "";
}
int objStart = this.offset - 1;
int ojbEnd = this.offset + semicolonIndx + 1;
this.offset = ojbEnd;
//descriptor
return this.raw.substring(objStart, ojbEnd);
}
private String parseArrayType() {
int arrStart = this.offset - 1;
this.parseFieldType();
int arrEnd = this.offset;
//descriptor
return this.raw.substring(arrStart, arrEnd);
}
}
複製代碼
MethodLookup.java
package org.itstack.demo.jvm.rtda.heap.methodarea;
/** * http://www.itstack.org * create by fuzhengwei on 2019/4/28 */
public class MethodLookup {
static public Method lookupMethodInClass(Class clazz, String name, String descriptor) {
for (Class c = clazz; c != null; c = c.superClass) {
for (Method method : c.methods) {
if (method.name.equals(name) && method.descriptor.equals(descriptor)) {
return method;
}
}
}
return null;
}
static public Method lookupMethodInInterfaces(Class[] ifaces, String name, String descriptor) {
for (Class inface : ifaces) {
for (Method method : inface.methods) {
if (method.name.equals(name) && method.descriptor.equals(descriptor)) {
return method;
}
}
}
return null;
}
}
複製代碼
Interpret.java
//指令集解釋器
class Interpret {
Interpret(Method method, boolean logInst) {
Thread thread = new Thread();
Frame frame = thread.newFrame(method);
thread.pushFrame(frame);
loop(thread, logInst);
}
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);
}
//exec
inst.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();
}
}
複製代碼
HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
long x = fibonacci(10);
System.out.println(x);
}
//斐波那契數列(Fibonacci sequence)
private static long fibonacci(long n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
複製代碼
斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖爲例子而引入,故又稱爲「兔子數列」,指的是這樣一個數列:一、一、二、三、五、八、1三、2一、3四、……在數學上,斐波納契數列以以下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用,爲此,美國數學會從1963年起出版了以《斐波納契數列季刊》爲名的一份數學雜誌,用於專門刊載這方面的研究成果。
HelloWorld.fibonacci 指令:
lload_0
lconst_1
lcmp
ifgt 7
lload_0
lreturn
lload_0
lconst_1
lsub
invokestatic org/itstack/demo/test/HelloWorld/fibonacci(J)J
lload_0
ldc2_w 2
lsub
invokestatic org/itstack/demo/test/HelloWorld/fibonacci(J)J
ladd
lreturn
複製代碼
執行過程:
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0x14 -> LDC2_W => 局部變量表:[{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":10},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":0}]
java/lang/Object.<clinit>() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:null 操做數棧:null
java/lang/Object.<clinit>() 寄存器(指令):0xb1 -> RETURN => 局部變量表:null 操做數棧:null
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":10},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":10},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x94 -> LCMP => 局部變量表:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x9d -> IFGT => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x65 -> LSUB => 局部變量表:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":10},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":9},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":9},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x94 -> LCMP => 局部變量表:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x9d -> IFGT => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x65 -> LSUB => 局部變量表:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":9},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":8},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x94 -> LCMP => 局部變量表:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x9d -> IFGT => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x0a -> LCONST_1 => 局部變量表:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x65 -> LSUB => 局部變量表:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":7},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":7},{"num":0},{"num":1},{"num":0},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x1e -> LLOAD_0 => 局部變量表:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}] 操做數棧:[{"num":0},{"num":0},{"num":0},{"num":0},{"num":0},{"num":0}]
... ...
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xad -> LRETURN => 局部變量表:[{"num":1},{"num":0},{"num":0},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":1},{"num":0},{"num":0},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x61 -> LADD => 局部變量表:[{"num":2},{"num":0},{"num":1},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":2},{"num":0},{"num":1},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xad -> LRETURN => 局部變量表:[{"num":3},{"num":0},{"num":1},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":3},{"num":0},{"num":1},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x61 -> LADD => 局部變量表:[{"num":5},{"num":0},{"num":3},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":5},{"num":0},{"num":3},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xad -> LRETURN => 局部變量表:[{"num":8},{"num":0},{"num":3},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":8},{"num":0},{"num":3},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x61 -> LADD => 局部變量表:[{"num":13},{"num":0},{"num":8},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":13},{"num":0},{"num":8},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xad -> LRETURN => 局部變量表:[{"num":21},{"num":0},{"num":8},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":21},{"num":0},{"num":8},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0x61 -> LADD => 局部變量表:[{"num":34},{"num":0},{"num":21},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":34},{"num":0},{"num":21},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.fibonacci() 寄存器(指令):0xad -> LRETURN => 局部變量表:[{"num":55},{"num":0},{"num":21},{"num":0},{"num":2},{"num":0}] 操做數棧:[{"num":55},{"num":0},{"num":21},{"num":0},{"num":2},{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0x40 -> LSTORE_1 => 局部變量表:[{"num":55},{"num":0},{"num":0}] 操做數棧:[{"num":55},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb2 -> GET_STATIC => 局部變量表:[{"num":55},{"num":0},{"num":0}] 操做數棧:[{"num":55},{"num":0},{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb8 -> INVOKE_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0x01 -> ACONST_NULL => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb3 -> PUT_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0x01 -> ACONST_NULL => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb3 -> PUT_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0x01 -> ACONST_NULL => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb3 -> PUT_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0x01 -> ACONST_NULL => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb3 -> PUT_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0x01 -> ACONST_NULL => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb3 -> PUT_STATIC => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
java/lang/System.<clinit>() 寄存器(指令):0xb1 -> RETURN => 局部變量表:[{"num":0}] 操做數棧:[{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb2 -> GET_STATIC => 局部變量表:[{"num":55},{"num":0},{"num":0}] 操做數棧:[{"num":55},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0x1f -> LLOAD_1 => 局部變量表:[{"num":55},{"num":0},{"num":0}] 操做數棧:[{"num":55},{"num":0},{"num":0}]
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb6 -> INVOKE_VIRTUAL => 局部變量表:[{"num":55},{"num":55},{"num":0}] 操做數棧:[{"num":55},{"num":55},{"num":0}]
55
org/itstack/demo/test/HelloWorld.main() 寄存器(指令):0xb1 -> RETURN => 局部變量表:[{"num":55},{"num":55},{"num":0}] 操做數棧:[{"num":55},{"num":55},{"num":0}]
複製代碼
微信搜索「bugstack蟲洞棧」公衆號,關注後回覆「用Java實現jvm源碼」獲取本文源碼&更多原創專題案例!