前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用Java实现JVM第七章《方法调用和返回》

用Java实现JVM第七章《方法调用和返回》

原创
作者头像
小傅哥
修改2020-01-20 09:43:20
4630
修改2020-01-20 09:43:20
举报
文章被收录于专栏:CodeGuide | 程序员编码指南

小傅哥 | https://bugstack.cn 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。目前已完成的专题有;Netty4.x实战专题案例、用Java实现JVM、基于JavaAgent的全链路监控、手写RPC框架、架构设计专题案例、源码分析等。 你用剑🗡、我用刀🔪,好的代码都很烧,望你不吝出招!

一、案例介绍

本章节主要用java实现;方法调用指令、返回指令、解析方法符号引用、参数传递等。实现新的指令后我们的虚拟机就可以执行稍微复杂的运算并输出结果。

从调用的角度来看,方法可以分为两类:静态方法(或者类方法)和实例方法。静态方法通过类类调用,实例方法则通过对象引用来调用。静态方法是静态绑定的,也就是说,最终调用的是哪给方法在编译期就已经确定。实例方法则支持动态绑定,最终要调用哪给方法可能要推迟到运行期才能知道。

从实现的角度来看,方法可以分为三类:没有实现(也就是抽象方法)、用Java语言(或者JVM上其他的语言,如Groovy和Scala等)实现和用本地语言(如C或者C++)实现。静态方法和抽象方法是互斥的。在Java 8之前,接口只能包括抽象方法。为了实现Lambda表达式,Java 8放宽了这一限制,在接口中也可以定义静态方法和默认方法。

在Java 7之前,Java虚拟机规范一共提供了4条方法调用指令。其中invokestatic指令用来调用静态方法。invokespecial指令用来调用无须动态绑定的实例方法,包括构造函数、私有方法和通过super关键字调用的超类方法。剩下的情况则属于动态绑定。如果是针对接口类型的引用调用方法,就使用invokeinterface指令,否则使用invokevirtual指令。

二、环境准备

  1. jdk 1.8.0
  2. IntelliJ IDEA Community Edition 2018.3.1 x64

三、配置信息

  1. 调试配置
代码语言:txt
复制
1. 配置位置:Run/Debug Configurations -> program arguments
代码语言:txt
复制
2. 配置内容(选配 verbose true):-Xjre "C:\Program Files\Java\jdk1.8.0\_161\jre" E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-07\target\test-classes\org\itstack\demo\test\HelloWorld verbose true

四、代码示例

代码语言:txt
复制
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.java

代码语言:txt
复制
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.java

代码语言:txt
复制
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.java

代码语言:txt
复制
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

代码语言:txt
复制
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.java

代码语言:txt
复制
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

代码语言:txt
复制
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

代码语言:txt
复制
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;

        //descripto

        return this.raw.substring(objStart, ojbEnd);

    }



    private String parseArrayType() {

        int arrStart = this.offset - 1;

        this.parseFieldType();

        int arrEnd = this.offset;

        //descripto

        return this.raw.substring(arrStart, arrEnd);

    }





}

MethodLookup.java

代码语言:txt
复制
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

代码语言:txt
复制
//指令集解释器

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

代码语言:txt
复制
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、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。

五、测试结果

jvm执行复杂计算:斐波那契数列,输出结果55

HelloWorld.fibonacci 指令:

代码语言:txt
复制
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

执行过程:

代码语言:txt
复制
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}]

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、案例介绍
  • 二、环境准备
  • 三、配置信息
  • 四、代码示例
  • 五、测试结果
相关产品与服务
应用性能监控
应用性能监控(Application Performance Management,APM)是一款应用性能管理平台,基于实时多语言应用探针全量采集技术,为您提供分布式性能分析和故障自检能力。APM 协助您在复杂的业务系统里快速定位性能问题,降低 MTTR(平均故障恢复时间),实时了解并追踪应用性能,提升用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档