龙空技术网

如何用Java实现JVM中的方法调用和返回?

月亮跌进深海里 202

前言:

当前我们对“java怎么返回数据”大约比较注意,朋友们都想要剖析一些“java怎么返回数据”的相关文章。那么小编也在网摘上收集了一些对于“java怎么返回数据””的相关内容,希望兄弟们能喜欢,你们一起来学习一下吧!

案例介绍

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

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

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

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

环境准备jdk 1.8.0IntelliJ IDEA Community Edition 2018.3.1 x64配置信息调试配置配置位置:Run/Debug Configurations -> program arguments配置内容(选配 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代码示例

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

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;/** *  * 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

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;/** *  * 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

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;/** *  * 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

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;/** *  * 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;/** *  * 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;/** *  * 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、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 指令:

lload_0lconst_1lcmpifgt 7lload_0lreturnlload_0lconst_1lsubinvokestatic org/itstack/demo/test/HelloWorld/fibonacci(J)Jlload_0ldc2_w 2lsubinvokestatic org/itstack/demo/test/HelloWorld/fibonacci(J)Jladdlreturn

执行过程:

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 操作数栈:nulljava/lang/Object.<clinit>() 	寄存器(指令):0xb1 -> RETURN => 局部变量表:null 操作数栈:nullorg/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}]55org/itstack/demo/test/HelloWorld.main() 	寄存器(指令):0xb1 -> RETURN => 局部变量表:[{"num":55},{"num":55},{"num":0}] 操作数栈:[{"num":55},{"num":55},{"num":0}]

今天的分享就到这了,我这里准备了一套java进阶方法笔记,学习资料面试题,电子书等免费笔记供大家学习.需要的小伙伴私信我回复"Java"即可领取免费资料.

java核心知识点

标签: #java怎么返回数据