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

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

2.jpg案例介绍

本章节主要用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、调试配置

2.1、配置位置:Run/Debug Configurations -> program arguments

2.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

代码示例

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

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

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.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;
/**
 * 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、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_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 => 局部变量表:[


目录
相关文章
|
1月前
|
Java
jvm复习,深入理解java虚拟机一:运行时数据区域
这篇文章深入探讨了Java虚拟机的运行时数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、元空间和运行时常量池,并讨论了它们的作用、特点以及与垃圾回收的关系。
64 19
jvm复习,深入理解java虚拟机一:运行时数据区域
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
32 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
27天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
1月前
|
存储 算法 Java
深入理解Java虚拟机(JVM)及其优化策略
【10月更文挑战第10天】深入理解Java虚拟机(JVM)及其优化策略
41 1
|
1月前
|
安全 Java API
🌟探索Java宇宙:深入理解Java技术体系与JVM的奥秘
本文深入探讨了Java技术体系的全貌,从Java语言的概述到其优点,再到Java技术体系的构成,以及JVM的角色。旨在帮助Java开发者全面了解Java生态,提升对Java技术的认知,从而在编程实践中更好地发挥Java的优势。关键词:Java, JVM, 技术体系, 编程语言, 跨平台, 内存管理。
38 2
|
1月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
44 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
1月前
|
监控 Java
Java的JVM如何优化?
Java的JVM如何优化?
57 3
|
2月前
|
存储 缓存 监控
【Java面试题汇总】JVM篇(2023版)
JVM内存模型、双亲委派模型、类加载机制、内存溢出、垃圾回收机制、内存泄漏、垃圾回收流程、垃圾回收器、G1、CMS、JVM调优
【Java面试题汇总】JVM篇(2023版)
|
2月前
|
安全 前端开发 Java
浅析JVM invokedynamic指令与Java Lambda语法的深度融合
在Java的演进历程中,Lambda表达式无疑是Java 8引入的一项革命性特性,它极大地简化了函数式编程在Java中的应用,使得代码更加简洁、易于阅读和维护。而这一切的背后,JVM的invokedynamic指令功不可没。本文将深入探讨invokedynamic指令的工作原理及其与Java Lambda语法的紧密联系,带您领略这一技术背后的奥秘。
30 1
|
1月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
37 4
下一篇
无影云桌面