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

用Java实现JVM第六章《类和对象》

原创
作者头像
小傅哥
修改2020-01-20 09:43:18
3610
修改2020-01-20 09:43:18
举报

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

一、案例介绍

本案例通过java代码实现jvm规范中指令集和解释器,完成后就可以开始执行1到100的加和计算。

Java虚拟机顾名思义,就是一台虚拟的机器,而字节码(bytecode)就是运行在这台虚拟机器上的机器码。我们已经知道,每一个类或者接口都会被Java编译器编译成一个class文件,类或接口的方法信息就放在class文件的method_info结构中。如果方法不是抽象的,也不是本地方法,方法的Java代码就会被编译器编译成字节码(即使方法是空的,编译器也会生成一条return语句),存在method_info结构的Code属性中。

二、环境准备

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

三、配置信息

  1. 调试配置
    1. 配置位置:Run/Debug Configurations -> program arguments
    2. 配置内容:-Xjre "C:\Program Files\Java\jdk1.8.0_161\jre" E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-06\target\test-classes\org\itstack\demo\test\HelloWorld

四、代码示例

代码语言:txt
复制
itstack-demo-jvm-06
├── 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
    │             │   ├── comparisons
    │             │   ├── constants
    │             │   ├── control
    │             │   ├── conversions
    │             │   ├── extended
    │             │   ├── loads
    │             │   ├── math
    │             │   │   ├── add
    │             │   │   ├── and
    │             │   │   ├── div
    │             │   │   ├── iinc
    │             │   │   ├── mul
    │             │   │   ├── neg
    │             │   │   ├── or
    │             │   │   ├── rem
    │             │   │   ├── sh
    │             │   │   ├── sub
    │             │   │   └── xor
    │             │   ├── stack
    │             │   ├── store
    │             │   └── Factory	
    │             ├── rtda
    │             │   ├── heap
    │             │   │   ├── constantpool
    │             │   │   ├── methodarea
    │             │   │   │   ├── Class.java 	
    │             │   │   │   ├── ClassMember.java	
    │             │   │   │   ├── Field.java	
    │             │   │   │   ├── Method.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

Class.java

代码语言:txt
复制
public class Class {

    public int accessFlags;
    public String name;
    public String superClassName;
    public String[] interfaceNames;
    public RunTimeConstantPool runTimeConstantPool;
    public Field[] fields;
    public Method[] methods;
    public ClassLoader loader;
    public Class superClass;
    public Class[] interfaces;
    public int instanceSlotCount;
    public int staticSlotCount;
    public Slots staticVars;

    public Class(ClassFile classFile) {
        this.accessFlags = classFile.accessFlags();
        this.name = classFile.className();
        this.superClassName = classFile.superClassName();
        this.interfaceNames = classFile.interfaceNames();
        this.runTimeConstantPool = new RunTimeConstantPool(this, classFile.constantPool());
        this.fields = new Field().newFields(this, classFile.fields());
        this.methods = new Method().newMethods(this, classFile.methods());
    }

    public boolean isPublic() {
        return 0 != (this.accessFlags & AccessFlags.ACC_PUBLIC);
    }

    public boolean isFinal() {
        return 0 != (this.accessFlags & AccessFlags.ACC_FINAL);
    }

    public boolean isSuper() {
        return 0 != (this.accessFlags & AccessFlags.ACC_SUPER);
    }

    public boolean isInterface() {
        return 0 != (this.accessFlags & AccessFlags.ACC_INTERFACE);
    }

    public boolean isAbstract() {
        return 0 != (this.accessFlags & AccessFlags.ACC_ABSTRACT);
    }

    public boolean isSynthetic() {
        return 0 != (this.accessFlags & AccessFlags.ACC_SYNTHETIC);
    }

    public boolean isAnnotation() {
        return 0 != (this.accessFlags & AccessFlags.ACC_ANNOTATION);
    }

    public boolean isEnum() {
        return 0 != (this.accessFlags & AccessFlags.ACC_ENUM);
    }

    public RunTimeConstantPool constantPool() {
        return this.runTimeConstantPool;
    }

    public Slots staticVars() {
        return this.staticVars;
    }

    public boolean isAccessibleTo(Class other) {
        return this.isPublic() || this.getPackageName().equals(other.getPackageName());
    }

    public String getPackageName() {
        int i = this.name.lastIndexOf("/");
        if (i >= 0) return this.name;
        return "";
    }

    public Method getMainMethod() {
        return this.getStaticMethod("main", "([Ljava/lang/String;)V");
    }

    private Method getStaticMethod(String name, String descriptor) {
        for (Method method : this.methods) {
            if (method.name.equals(name) && method.descriptor.equals(descriptor)) {
                return method;
            }
        }
        return null;
    }

    public Object newObject() {
        return new Object(this);
    }

    public boolean isAssignableFrom(Class other) {
        if (this == other) return true;
        if (!other.isInterface()) {
            return this.isSubClassOf(other);
        } else {
            return this.isImplements(other);
        }
    }

    public boolean isSubClassOf(Class other) {
        for (Class c = this.superClass; c != null; c = c.superClass) {
            if (c == other) {
                return true;
            }
        }
        return false;
    }

    private boolean isImplements(Class other) {

        for (Class c = this; c != null; c = c.superClass) {
            for (Class clazz : c.interfaces) {
                if (clazz == other || clazz.isSubInterfaceOf(other)) {
                    return true;
                }
            }
        }
        return false;

    }

    public boolean isSubInterfaceOf(Class iface) {
        for (Class superInterface : this.interfaces) {
            if (superInterface == iface || superInterface.isSubInterfaceOf(iface)) {
                return true;
            }
        }
        return false;
    }

}

ClassMember.java

代码语言:txt
复制
public class ClassMember {

    public int accessFlags;
    public String name;
    public String descriptor;
    public Class clazz;

    public void copyMemberInfo(MemberInfo memberInfo) {
        this.accessFlags = memberInfo.accessFlags();
        this.name = memberInfo.name();
        this.descriptor = memberInfo.descriptor();
    }

    public boolean isPublic() {
        return 0 != (this.accessFlags & AccessFlags.ACC_PUBLIC);
    }

    public boolean isPrivate() {
        return 0 != (this.accessFlags & AccessFlags.ACC_PRIVATE);
    }

    public boolean isProtected() {
        return 0 != (this.accessFlags & AccessFlags.ACC_PROTECTED);
    }

    public boolean isStatic() {
        return 0 != (this.accessFlags & AccessFlags.ACC_STATIC);
    }

    public boolean isFinal() {
        return 0 != (this.accessFlags & AccessFlags.ACC_FINAL);
    }

    public boolean isSynthetic() {
        return 0 != (this.accessFlags & AccessFlags.ACC_SYNTHETIC);
    }

    public String name() {
        return this.name;
    }

    public String descriptor() {
        return this.descriptor;
    }

    public Class clazz() {
        return this.clazz;
    }

    public boolean isAccessibleTo(Class d) {
        if (this.isPublic()) {
            return true;
        }
        Class c = this.clazz;
        if (this.isProtected()) {
            return d == c || c.getPackageName().equals(d.getPackageName());
        }
        if (!this.isPrivate()) {
            return c.getPackageName().equals(d.getPackageName());
        }
        return d == c;
    }

}

Field.java

代码语言:txt
复制
package org.itstack.demo.jvm.rtda.heap.methodarea;

import org.itstack.demo.jvm.classfile.MemberInfo;
import org.itstack.demo.jvm.classfile.attributes.impl.ConstantValueAttribute;
import org.itstack.demo.jvm.rtda.heap.constantpool.AccessFlags;

public class Field extends ClassMember {

    public int constValueIndex;
    public int slotId;

    public Field[] newFields(Class clazz, MemberInfo[] cfFields) {
        Field[] fields = new Field[cfFields.length];
        for (int i = 0; i < cfFields.length; i++) {
            fields[i] = new Field();
            fields[i].clazz = clazz;
            fields[i].copyMemberInfo(cfFields[i]);
            fields[i].copyAttributes(cfFields[i]);
        }
        return fields;
    }

    public void copyAttributes(MemberInfo cfField) {
        ConstantValueAttribute valAttr = cfField.ConstantValueAttribute();
        if (null != valAttr) {
            this.constValueIndex = valAttr.constantValueIdx();
        }
    }

    public boolean isVolatile() {
        return 0 != (this.accessFlags & AccessFlags.ACC_VOLATILE);
    }

    public boolean isTransient() {
        return 0 != (this.accessFlags & AccessFlags.ACC_TRANSIENT);
    }

    public boolean isEnum() {
        return 0 != (this.accessFlags & AccessFlags.ACC_ENUM);
    }

    public int constValueIndex() {
        return this.constValueIndex;
    }

    public int slotId() {
        return this.slotId;
    }

    public boolean isLongOrDouble() {
        return this.descriptor.equals("J") || this.descriptor.equals("D");
    }


}

Method.java

代码语言:txt
复制
package org.itstack.demo.jvm.rtda.heap.methodarea;

import org.itstack.demo.jvm.classfile.MemberInfo;
import org.itstack.demo.jvm.classfile.attributes.impl.CodeAttribute;
import org.itstack.demo.jvm.rtda.heap.constantpool.AccessFlags;

public class Method extends ClassMember {

    public int maxStack;
    public int maxLocals;
    public byte[] code;

    public Method[] newMethods(Class clazz, MemberInfo[] cfMethods) {
        Method[] methods = new Method[cfMethods.length];
        for (int i = 0; i < cfMethods.length; i++) {
            methods[i] = new Method();
            methods[i].clazz = clazz;
            methods[i].copyMemberInfo(cfMethods[i]);
            methods[i].copyAttributes(cfMethods[i]);
        }
        return methods;
    }

    public void copyAttributes(MemberInfo cfMethod) {
        CodeAttribute codeAttr = cfMethod.codeAttribute();
        if (null != codeAttr) {
            this.maxStack = codeAttr.maxStack();
            this.maxLocals = codeAttr.maxLocals();
            this.code = codeAttr.data();
        }
    }

    public boolean isSynchronized() {
        return 0 != (this.accessFlags & AccessFlags.ACC_SYNCHRONIZED);
    }

    public boolean isBridge() {
        return 0 != (this.accessFlags & AccessFlags.ACC_BRIDGE);
    }

    public boolean isVarargs() {
        return 0 != (this.accessFlags & AccessFlags.ACC_VARARGS);
    }

    public boolean isNative() {
        return 0 != (this.accessFlags & AccessFlags.ACC_NATIVE);
    }

    public boolean isAbstract() {
        return 0 != (this.accessFlags & AccessFlags.ACC_ABSTRACT);
    }

    public boolean isStrict() {
        return 0 != (this.accessFlags & AccessFlags.ACC_STRICT);
    }

    public int maxStack() {
        return this.maxStack;
    }

    public int maxLocals() {
        return this.maxLocals;
    }

    public byte[] code() {
        return this.code;
    }

}

Object.java

代码语言:txt
复制
package org.itstack.demo.jvm.rtda.heap.methodarea;

public class Object {

    Class clazz;
    Slots fields;

    public Object(Class clazz){
        this.clazz = clazz;
        this.fields = new Slots(clazz.instanceSlotCount);
    }

    public Class clazz(){
        return this.clazz;
    }

    public Slots fields(){
        return this.fields;
    }

    public boolean isInstanceOf(Class clazz){
        return clazz.isAssignableFrom(this.clazz);
    }

}

Slots.java

代码语言:txt
复制
package org.itstack.demo.jvm.rtda.heap.methodarea;

import org.itstack.demo.jvm.rtda.Slot;

public class Slots {

    private Slot[] slots;

    public Slots(int slotCount) {
        if (slotCount > 0) {
            slots = new Slot[slotCount];
            for (int i = 0; i < slotCount; i++) {
                slots[i] = new Slot();
            }
        }
    }

    public void setInt(int idx, int val) {
        this.slots[idx].num = val;
    }

    public int getInt(int idx) {
        return this.slots[idx].num;
    }

    public void setFloat(int idx, float val) {
        this.slots[idx].num = (int) val;
    }

    public float getFloat(int idx) {
        return this.slots[idx].num;
    }

    public void setLong(int idx, long val) {
        this.slots[idx].num = (int) val;
        this.slots[idx + 1].num = (int) (val >> 32);
    }

    public long getLong(int idx) {
        int low = this.slots[idx].num;
        int high = this.slots[idx + 1].num;
        return (long) high << 32 | (long) low;
    }

    public void setDouble(int idx, double val) {
        this.setLong(idx, (long) val);
    }

    public Double getDouble(int idx) {
        return (double) this.getLong(idx);
    }

    public void setRef(int idx, Object ref) {
        this.slots[idx].ref = ref;
    }

    public Object getRef(int idx){
        return this.slots[idx].ref;
    }

}

五、测试结果

可以看到已经输出;5050

代码语言:txt
复制
"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\lib\idea_rt.jar=61887:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\classes;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\beust\jcommander\1.72\jcommander-1.72.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\org\projectlombok\lombok\1.18.0\lombok-1.18.0.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\alibaba\fastjson\1.2.40\fastjson-1.2.40.jar" org.itstack.demo.jvm.Main -Xjre "C:\Program Files\Java\jdk1.8.0_161\jre" E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\test-classes\org\itstack\demo\test\HelloWorld
classpath:org.itstack.demo.jvm.classpath.Classpath@4bf558aa class:E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\test-classes\org\itstack\demo\test\HelloWorld args:null
寄存器(指令):0x03 -> ICONST_0 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x3c -> ISTORE_1 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x04 -> ICONST_1 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x3d -> ISTORE_2 => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0xa3 -> IF_ICMPGT => 局部变量表:[{"num":1},{"num":100}] 操作数栈:[{"num":1},{"num":100}]
寄存器(指令):0x1b -> ILOAD_1 => 局部变量表:[{"num":1},{"num":100}] 操作数栈:[{"num":1},{"num":100}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":0},{"num":100}] 操作数栈:[{"num":0},{"num":100}]

... ...

寄存器(指令):0x60 -> IADD => 局部变量表:[{"num":4950},{"num":100}] 操作数栈:[{"num":4950},{"num":100}]
寄存器(指令):0x3c -> ISTORE_1 => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x84 -> IINC => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0xa7 -> GOTO => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":101},{"num":100}] 操作数栈:[{"num":101},{"num":100}]
寄存器(指令):0xa3 -> IF_ICMPGT => 局部变量表:[{"num":101},{"num":100}] 操作数栈:[{"num":101},{"num":100}]
5050
寄存器(指令):0xb1 -> RETURN => 局部变量表:[{"num":101},{"num":5050}] 操作数栈:[{"num":101},{"num":5050}]
Exception in thread "main" java.lang.RuntimeException: jvm stack is empty!
	at org.itstack.demo.jvm.rtda.JvmStack.pop(JvmStack.java:33)

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

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

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

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

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