侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

用Java实现JVM第三章《解析class文件》

2022-07-11 星期一 / 0 评论 / 0 点赞 / 39 阅读 / 45156 字

案例介绍本案例主要介绍通过java代码从class文件中解析;class文件、常量池、属性表;作为类(或者接口)信息的载体,每个class文件都完整地定义了一个类。为了使java程序可以“编写一次,处

案例介绍

本案例主要介绍通过java代码从class文件中解析;class文件、常量池、属性表;

.

作为类(或者接口)信息的载体,每个class文件都完整地定义了一个类。为了使java程序可以“编写一次,处处运行”,Java虚拟机规范对class文件格式进行了严格的规定。但是另外一方面,对于从哪里加载class文件,给了足够多的自由。Java虚拟机实现可以从文件系统读取和从JAR(或ZIP)压缩包中提取clss文件。除此之外,也可以通过网络下载、从数据库加载,甚至是在运行中直接生成class文件。Java虚拟机规范中所指的class文件,并非特指位于磁盘中的.class文件,而是泛指任何格式符号规范的class数据。

.

环境准备

  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" java.lang.String

代码示例

itstack-demo-jvm-03├── 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        │             ├── Cmd.java    │             └── Main.java    └── test         └── java             └── org.itstack.demo.test                 └── HelloWorld.java

代码篇幅较长,不一一列举,需要源码可以关注公众号:bugstack虫洞栈

.

AttributeInfo.java

.
package org.itstack.demo.jvm.classfile.attributes;import org.itstack.demo.jvm.classfile.ClassReader;import org.itstack.demo.jvm.classfile.attributes.impl.*;import org.itstack.demo.jvm.classfile.constantpool.ConstantPool;/** * http://www.itstack.org * create by fuzhengwei on 2019/4/26 */public interface AttributeInfo {    void readInfo(ClassReader reader);    static AttributeInfo[] readAttributes(ClassReader reader, ConstantPool constantPool) {        int attributesCount = reader.readU2ToInt();        AttributeInfo[] attributes = new AttributeInfo[attributesCount];        for (int i = 0; i < attributesCount; i++) {            attributes[i] = readAttribute(reader, constantPool);        }        return attributes;    }    static AttributeInfo readAttribute(ClassReader reader, ConstantPool constantPool) {        int attrNameIdx = reader.readU2ToInt();        String attrName = constantPool.getUTF8(attrNameIdx);        int attrLen = reader.readU4ToInt();        AttributeInfo attrInfo = newAttributeInfo(attrName, attrLen, constantPool);        attrInfo.readInfo(reader);        return attrInfo;    }    static AttributeInfo newAttributeInfo(String attrName, int attrLen, ConstantPool constantPool) {        switch (attrName) {            case "BootstrapMethods":                return new BootstrapMethodsAttribute();            case "Code":                return new CodeAttribute(constantPool);            case "ConstantValue":                return new ConstantValueAttribute();            case "Deprecated":                return new DeprecatedAttribute();            case "EnclosingMethod":                return new EnclosingMethodAttribute(constantPool);            case "Exceptions":                return new ExceptionsAttribute();            case "InnerClasses":                return new InnerClassesAttribute();            case "LineNumberTable":                return new LineNumberTableAttribute();            case "LocalVariableTable":                return new LocalVariableTableAttribute();            case "LocalVariableTypeTable":                return new LocalVariableTypeTableAttribute();            // case "MethodParameters":            // case "RuntimeInvisibleAnnotations":            // case "RuntimeInvisibleParameterAnnotations":            // case "RuntimeInvisibleTypeAnnotations":            // case "RuntimeVisibleAnnotations":            // case "RuntimeVisibleParameterAnnotations":            // case "RuntimeVisibleTypeAnnotations":            case "Signature":                return new SignatureAttribute(constantPool);            case "SourceFile":                return new SourceFileAttribute(constantPool);            // case "SourceDebugExtension":            // case "StackMapTable":            case "Synthetic":                return new SyntheticAttribute();            default:                return new UnparsedAttribute(attrName, attrLen);        }    }}
.

ConstantInfo.java

.
package org.itstack.demo.jvm.classfile.constantpool;import org.itstack.demo.jvm.classfile.ClassReader;import org.itstack.demo.jvm.classfile.constantpool.impl.*;/** * http://www.itstack.org * create by fuzhengwei on 2019/4/26 */public interface ConstantInfo {    int CONSTANT_TAG_CLASS = 7;    int CONSTANT_TAG_FIELDREF = 9;    int CONSTANT_TAG_METHODREF = 10;    int CONSTANT_TAG_INTERFACEMETHODREF = 11;    int CONSTANT_TAG_STRING = 8;    int CONSTANT_TAG_INTEGER = 3;    int CONSTANT_TAG_FLOAT = 4;    int CONSTANT_TAG_LONG = 5;    int CONSTANT_TAG_DOUBLE = 6;    int CONSTANT_TAG_NAMEANDTYPE = 12;    int CONSTANT_TAG_UTF8 = 1;    int CONSTANT_TAG_METHODHANDLE = 15;    int CONSTANT_TAG_METHODTYPE = 16;    int CONSTANT_TAG_INVOKEDYNAMIC = 18;    void readInfo(ClassReader reader);    int tag();        static ConstantInfo readConstantInfo(ClassReader reader, ConstantPool constantPool) {        int tag = reader.readU1ToInt();        ConstantInfo constantInfo = newConstantInfo(tag, constantPool);        constantInfo.readInfo(reader);        return constantInfo;    }    static ConstantInfo newConstantInfo(int tag, ConstantPool constantPool) {        switch (tag) {            case CONSTANT_TAG_INTEGER:                return new ConstantIntegerInfo();            case CONSTANT_TAG_FLOAT:                return new ConstantFloatInfo();            case CONSTANT_TAG_LONG:                return new ConstantLongInfo();            case CONSTANT_TAG_DOUBLE:                return new ConstantDoubleInfo();            case CONSTANT_TAG_UTF8:                return new ConstantUtf8Info();            case CONSTANT_TAG_STRING:                return new ConstantStringInfo(constantPool);            case CONSTANT_TAG_CLASS:                return new ConstantClassInfo(constantPool);            case CONSTANT_TAG_FIELDREF:                return new ConstantFieldRefInfo(constantPool);            case CONSTANT_TAG_METHODREF:                return new ConstantMethodRefInfo(constantPool);            case CONSTANT_TAG_INTERFACEMETHODREF:                return new ConstantInterfaceMethodRefInfo(constantPool);            case CONSTANT_TAG_NAMEANDTYPE:                return new ConstantNameAndTypeInfo();            case CONSTANT_TAG_METHODTYPE:                return new ConstantMethodTypeInfo();            case CONSTANT_TAG_METHODHANDLE:                return new ConstantMethodHandleInfo();            case CONSTANT_TAG_INVOKEDYNAMIC:                return new ConstantInvokeDynamicInfo();            default:                throw new ClassFormatError("constant pool tag");        }    }}
.

ClassFile.java

.
package org.itstack.demo.jvm.classfile;import org.itstack.demo.jvm.classfile.attributes.AttributeInfo;import org.itstack.demo.jvm.classfile.constantpool.ConstantPool;/** * http://www.itstack.org * create by fuzhengwei on 2019/4/26 */public class ClassFile {    private int minorVersion;    private int majorVersion;    private ConstantPool constantPool;    private int accessFlags;    private int thisClassIdx;    private int supperClassIdx;    private int[] interfaces;    private MemberInfo[] fields;    private MemberInfo[] methods;    private AttributeInfo[] attributes;    public ClassFile(byte[] classData) {        ClassReader reader = new ClassReader(classData);        this.readAndCheckMagic(reader);        this.readAndCheckVersion(reader);        this.constantPool = this.readConstantPool(reader);        this.accessFlags = reader.readU2ToInt();        this.thisClassIdx = reader.readU2ToInt();        this.supperClassIdx = reader.readU2ToInt();        this.interfaces = reader.readUInt16s();        this.fields = MemberInfo.readMembers(reader, constantPool);        this.methods = MemberInfo.readMembers(reader, constantPool);        this.attributes = AttributeInfo.readAttributes(reader, constantPool);    }    private void readAndCheckMagic(ClassReader reader) {        String magic = reader.readU4ToHexStr();        if (!"cafebabe".equals(magic)) {            throw new ClassFormatError("magic!");        }    }    private void readAndCheckVersion(ClassReader reader) {        this.minorVersion = reader.readU2ToInt();        this.majorVersion = reader.readU2ToInt();        switch (this.majorVersion) {            case 45:                return;            case 46:            case 47:            case 48:            case 49:            case 50:            case 51:            case 52:                if (this.minorVersion == 0)                    return;        }        throw new UnsupportedClassVersionError();    }    private ConstantPool readConstantPool(ClassReader reader) {        return new ConstantPool(reader);    }    public int minorVersion(){        return this.minorVersion;    }    public int majorVersion(){        return this.majorVersion;    }    public ConstantPool constantPool(){        return this.constantPool;    }    public int accessFlags() {        return this.accessFlags;    }    public MemberInfo[] fields() {        return this.fields;    }    public MemberInfo[] methods() {        return this.methods;    }    public String className() {        return this.constantPool.getClassName(this.thisClassIdx);    }    public String superClassName() {        if (this.supperClassIdx <= 0) return "";        return this.constantPool.getClassName(this.supperClassIdx);    }    public String[] interfaceNames() {        String[] interfaceNames = new String[this.interfaces.length];        for (int i = 0; i < this.interfaces.length; i++) {            interfaceNames[i] = this.constantPool.getClassName(interfaces[i]);        }        return interfaceNames;    }}
.

ClassReader.java

.
package org.itstack.demo.jvm.classfile;import java.math.BigInteger;/** * http://www.itstack.org * create by fuzhengwei on 2019/5/13 * <p> * java虚拟机定义了u1、u2、u4三种数据类型来表示;1字节、2字节、4字节,无符号整数。 * 在如下实现中,用增位方式表示无符号类型: * u1、u2可以用int类型存储,因为int类型是4字节 * u4 需要用long类型存储,因为long类型是8字节 */public class ClassReader {    private byte[] data;    public ClassReader(byte[] data) {        this.data = data;    }    //u1    public int readUint8() {        byte[] val = readByte(1);        return byte2int(val);    }    //u2    public int readUint16() {        byte[] val = readByte(2);        return byte2int(val);    }    //u4    public long readUint32() {        byte[] val = readByte(4);        String str_hex = new BigInteger(1, val).toString(16);        return Long.parseLong(str_hex, 16);    }    public float readUint64TFloat() {        byte[] val = readByte(8);        return new BigInteger(1, val).floatValue();    }    public long readUint64TLong() {        byte[] val = readByte(8);        return new BigInteger(1, val).longValue();    }    public double readUint64TDouble() {        byte[] val = readByte(8);        return new BigInteger(1, val).doubleValue();    }    public int[] readUint16s() {        int n = this.readUint16();        int[] s = new int[n];        for (int i = 0; i < n; i++) {            s[i] = this.readUint16();        }        return s;    }    public byte[] readBytes(int n) {        return readByte(n);    }    private byte[] readByte(int length) {        byte[] copy = new byte[length];        System.arraycopy(data, 0, copy, 0, length);        System.arraycopy(data, length, data, 0, data.length - length);        return copy;    }    private int byte2int(byte[] val) {        String str_hex = new BigInteger(1, val).toString(16);        return Integer.parseInt(str_hex, 16);    }}
.

MemberInfo.java

.
package org.itstack.demo.jvm.classfile;import org.itstack.demo.jvm.classfile.attributes.AttributeInfo;import org.itstack.demo.jvm.classfile.attributes.impl.CodeAttribute;import org.itstack.demo.jvm.classfile.attributes.impl.ConstantValueAttribute;import org.itstack.demo.jvm.classfile.constantpool.ConstantPool;/** * http://www.itstack.org * create by fuzhengwei on 2019/4/26 */public class MemberInfo {    private ConstantPool constantPool;    private int accessFlags;    private int nameIdx;    private int descriptorIdx;    private AttributeInfo[] attributes;    public MemberInfo(ClassReader reader, ConstantPool constantPool) {        this.constantPool = constantPool;        this.accessFlags = reader.readU2ToInt();        this.nameIdx = reader.readU2ToInt();        this.descriptorIdx = reader.readU2ToInt();        this.attributes = AttributeInfo.readAttributes(reader, constantPool);    }    public static MemberInfo[] readMembers(ClassReader reader, ConstantPool constantPool) {        int fieldCount = reader.readU2ToInt();        MemberInfo[] fields = new MemberInfo[fieldCount];        for (int i = 0; i < fieldCount; i++) {            fields[i] = new MemberInfo(reader, constantPool);        }        return fields;    }    public int accessFlags() {        return this.accessFlags;    }    public String name() {        return this.constantPool.getUTF8(this.nameIdx);    }    public String descriptor() {        return this.constantPool.getUTF8(this.descriptorIdx);    }    public CodeAttribute codeAttribute() {        for (AttributeInfo attrInfo : attributes) {            if (attrInfo instanceof CodeAttribute) return (CodeAttribute) attrInfo;        }        return null;    }    public ConstantValueAttribute ConstantValueAttribute() {        for (AttributeInfo attrInfo : attributes) {            if (attrInfo instanceof ConstantValueAttribute) return (ConstantValueAttribute) attrInfo;        }        return null;    }}
.

Main.java

.
package org.itstack.demo.jvm;import org.itstack.demo.jvm.classfile.ClassFile;import org.itstack.demo.jvm.classfile.MemberInfo;import org.itstack.demo.jvm.classpath.Classpath;import java.util.Arrays;/** * http://www.itstack.org * create by fuzhengwei on 2019/4/24 */public class Main {    public static void main(String[] args) {        Cmd cmd = Cmd.parse(args);        if (!cmd.ok || cmd.helpFlag) {            System.out.println("Usage: <main class> [-options] class [args...]");            return;        }        if (cmd.versionFlag) {            //注意案例测试都是基于1.8,另外jdk1.9以后使用模块化没有rt.jar            System.out.println("java version /"1.8.0/"");            return;        }        startJVM(cmd);    }    private static void startJVM(Cmd cmd) {        Classpath classpath = new Classpath(cmd.jre, cmd.classpath);        System.out.printf("classpath:%s class:%s args:%s/n",                classpath, cmd.getMainClass(), cmd.getAppArgs());        //获取className        String className = cmd.getMainClass().replace(".", "/");        ClassFile classFile = loadClass(className, classpath);        assert classFile != null;        printClassInfo(classFile);    }    private static ClassFile loadClass(String className, Classpath classpath) {        try {            byte[] classData = classpath.readClass(className);            return new ClassFile(classData);        } catch (Exception e) {            System.out.println("Could not find or load main class " + className);            return null;        }    }    private static void printClassInfo(ClassFile cf) {        System.out.println("version: " + cf.majorVersion() + "." + cf.minorVersion());        System.out.println("constants count:" + cf.constantPool().getSiz());        System.out.format("access flags:0x%x/n", cf.accessFlags());        System.out.println("this class:" + cf.className());        System.out.println("super class:" + cf.superClassName());        System.out.println("interfaces:" + Arrays.toString(cf.interfaceNames()));        System.out.println("fields count:" + cf.fields().length);        for (MemberInfo memberInfo : cf.fields()) {            System.out.format("  %s/n", memberInfo.name());        }        System.out.println("methods count: " + cf.methods().length);        for (MemberInfo memberInfo : cf.methods()) {            System.out.format("  %s/n", memberInfo.name());        }    }}

测试结果

"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=61458: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-03/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" java.lang.Stringclasspath:org.itstack.demo.jvm.classpath.Classpath@4bf558aa class:java.lang.String args:nullversion: 52.0constants count:540access flags:0x31this class:java/lang/Stringsuper class:java/lang/Objectinterfaces:[java/io/Serializable, java/lang/Comparable, java/lang/CharSequence]fields count:5value 		 [Chash 		 IserialVersionUID 		 JserialPersistentFields 		 [Ljava/io/ObjectStreamField;CASE_INSENSITIVE_ORDER 		 Ljava/util/Comparator;methods count: 94<init> 		 ()V<init> 		 (Ljava/lang/String;)V<init> 		 ([C)V<init> 		 ([CII)V<init> 		 ([III)V<init> 		 ([BIII)V<init> 		 ([BI)VcheckBounds 		 ([BII)V<init> 		 ([BIILjava/lang/String;)V<init> 		 ([BIILjava/nio/charset/Charset;)V<init> 		 ([BLjava/lang/String;)V<init> 		 ([BLjava/nio/charset/Charset;)V<init> 		 ([BII)V<init> 		 ([B)V<init> 		 (Ljava/lang/StringBuffer;)V<init> 		 (Ljava/lang/StringBuilder;)V<init> 		 ([CZ)Vlength 		 ()IisEmpty 		 ()ZcharAt 		 (I)CcodePointAt 		 (I)IcodePointBefore 		 (I)IcodePointCount 		 (II)IoffsetByCodePoints 		 (II)IgetChars 		 ([CI)VgetChars 		 (II[CI)VgetBytes 		 (II[BI)VgetBytes 		 (Ljava/lang/String;)[BgetBytes 		 (Ljava/nio/charset/Charset;)[BgetBytes 		 ()[Bequals 		 (Ljava/lang/Object;)ZcontentEquals 		 (Ljava/lang/StringBuffer;)ZnonSyncContentEquals 		 (Ljava/lang/AbstractStringBuilder;)ZcontentEquals 		 (Ljava/lang/CharSequence;)ZequalsIgnoreCase 		 (Ljava/lang/String;)ZcompareTo 		 (Ljava/lang/String;)IcompareToIgnoreCase 		 (Ljava/lang/String;)IregionMatches 		 (ILjava/lang/String;II)ZregionMatches 		 (ZILjava/lang/String;II)ZstartsWith 		 (Ljava/lang/String;I)ZstartsWith 		 (Ljava/lang/String;)ZendsWith 		 (Ljava/lang/String;)ZhashCode 		 ()IindexOf 		 (I)IindexOf 		 (II)IindexOfSupplementary 		 (II)IlastIndexOf 		 (I)IlastIndexOf 		 (II)IlastIndexOfSupplementary 		 (II)IindexOf 		 (Ljava/lang/String;)IindexOf 		 (Ljava/lang/String;I)IindexOf 		 ([CIILjava/lang/String;I)IindexOf 		 ([CII[CIII)IlastIndexOf 		 (Ljava/lang/String;)IlastIndexOf 		 (Ljava/lang/String;I)IlastIndexOf 		 ([CIILjava/lang/String;I)IlastIndexOf 		 ([CII[CIII)Isubstring 		 (I)Ljava/lang/String;substring 		 (II)Ljava/lang/String;subSequence 		 (II)Ljava/lang/CharSequence;concat 		 (Ljava/lang/String;)Ljava/lang/String;replace 		 (CC)Ljava/lang/String;matches 		 (Ljava/lang/String;)Zcontains 		 (Ljava/lang/CharSequence;)ZreplaceFirst 		 (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;replaceAll 		 (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;replace 		 (Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;split 		 (Ljava/lang/String;I)[Ljava/lang/String;split 		 (Ljava/lang/String;)[Ljava/lang/String;join 		 (Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String;join 		 (Ljava/lang/CharSequence;Ljava/lang/Iterable;)Ljava/lang/String;toLowerCase 		 (Ljava/util/Locale;)Ljava/lang/String;toLowerCase 		 ()Ljava/lang/String;toUpperCase 		 (Ljava/util/Locale;)Ljava/lang/String;toUpperCase 		 ()Ljava/lang/String;trim 		 ()Ljava/lang/String;toString 		 ()Ljava/lang/String;toCharArray 		 ()[Cformat 		 (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;format 		 (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;valueOf 		 (Ljava/lang/Object;)Ljava/lang/String;valueOf 		 ([C)Ljava/lang/String;valueOf 		 ([CII)Ljava/lang/String;copyValueOf 		 ([CII)Ljava/lang/String;copyValueOf 		 ([C)Ljava/lang/String;valueOf 		 (Z)Ljava/lang/String;valueOf 		 (C)Ljava/lang/String;valueOf 		 (I)Ljava/lang/String;valueOf 		 (J)Ljava/lang/String;valueOf 		 (F)Ljava/lang/String;valueOf 		 (D)Ljava/lang/String;intern 		 ()Ljava/lang/String;compareTo 		 (Ljava/lang/Object;)I<clinit> 		 ()VProcess finished with exit code 0

上一篇:用Java实现JVM第二章《搜索class文件》

下一篇:用Java实现JVM第三章《解析class文件》附(classReader拆解)

微信搜索「bugstack虫洞栈」公众号,关注后回复「用Java实现jvm源码」获取本文源码&更多原创专题案例!

.
.

广告 广告

评论区