├── img.png ├── img_1.png ├── img_2.png ├── img_3.png ├── img_4.png ├── img_5.png ├── img_6.png ├── img_7.png ├── .gitignore ├── src └── main │ └── java │ └── com │ └── cover │ └── jvm │ ├── jdk │ └── classes │ │ ├── java │ │ └── lang │ │ │ └── Class.java │ │ ├── sun │ │ ├── launcher │ │ │ └── LauncherHelper.java │ │ └── misc │ │ │ ├── AppClassLoader.java │ │ │ ├── Unsafe.java │ │ │ └── ClassLoader.java │ │ ├── Threads.java │ │ ├── JniEnv.java │ │ └── Handle.java │ ├── hotspot │ └── src │ │ └── share │ │ ├── vm │ │ ├── oops │ │ │ ├── Klass.java │ │ │ ├── Annotation.java │ │ │ ├── FieldInfo.java │ │ │ ├── AttributeInfo.java │ │ │ ├── InterfaceInfo.java │ │ │ ├── RuntimeVisibleAnnotations.java │ │ │ ├── RuntimeInvisibleAnnotations.java │ │ │ ├── LineNumberTable.java │ │ │ ├── LocalVariableTable.java │ │ │ ├── InnerClasses.java │ │ │ ├── BootstrapMethods.java │ │ │ ├── CodeAttributeInfo.java │ │ │ ├── MethodInfo.java │ │ │ ├── DescriptorInfo.java │ │ │ ├── ArrayOop.java │ │ │ ├── InstanceKlass.java │ │ │ └── ConstantPool.java │ │ ├── runtime │ │ │ ├── Thread.java │ │ │ ├── VFrame.java │ │ │ ├── JavaThread.java │ │ │ ├── JavaVFrame.java │ │ │ ├── Threads.java │ │ │ ├── StackValue.java │ │ │ └── StackValueCollection.java │ │ ├── memory │ │ │ ├── AllocateObj.java │ │ │ ├── StackObj.java │ │ │ ├── AllStatic.java │ │ │ └── ResourceObj.java │ │ ├── classfile │ │ │ ├── StackMapTable.java │ │ │ ├── BootClassLoader.java │ │ │ ├── DescriptorStream.java │ │ │ ├── DescriptorStream2.java │ │ │ └── ClassFileParser.java │ │ ├── utilities │ │ │ ├── AccessFlags.java │ │ │ └── BasicType.java │ │ ├── interpreter │ │ │ ├── BytecodeStream.java │ │ │ ├── BaseBytecodeStream.java │ │ │ ├── LambdaEngine.java │ │ │ └── Bytecodes.java │ │ └── prims │ │ │ └── JavaNativeInterface.java │ │ └── tools │ │ ├── Stream.java │ │ └── DataTranslate.java │ ├── example │ └── java │ │ └── lang │ │ ├── lambda │ │ ├── CustomLambda.java │ │ ├── CustomLambda1.java │ │ ├── CustomLambda2.java │ │ ├── CustomLambdaParams.java │ │ └── TestLambda.java │ │ ├── operation │ │ ├── BitCount.java │ │ ├── InstanceOf.java │ │ ├── Else.java │ │ ├── SubSub.java │ │ ├── Div.java │ │ ├── Mul.java │ │ ├── Rem.java │ │ ├── Sub.java │ │ ├── Add.java │ │ └── AddAdd.java │ │ ├── HelloWorld.java │ │ ├── compare │ │ └── Integer.java │ │ ├── array │ │ └── Array.java │ │ └── condition │ │ ├── IfNull.java │ │ ├── IfOther.java │ │ └── IfInt.java │ └── Main.java ├── .idea ├── vcs.xml ├── encodings.xml ├── .gitignore ├── compiler.xml ├── jarRepositories.xml └── uiDesigner.xml ├── pom.xml └── README.md /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img.png -------------------------------------------------------------------------------- /img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_1.png -------------------------------------------------------------------------------- /img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_2.png -------------------------------------------------------------------------------- /img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_3.png -------------------------------------------------------------------------------- /img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_4.png -------------------------------------------------------------------------------- /img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_5.png -------------------------------------------------------------------------------- /img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_6.png -------------------------------------------------------------------------------- /img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2over/XVM/HEAD/img_7.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | target/ 3 | target/classes/com/jvm/Main.class 4 | *.iml 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/java/lang/Class.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes.java.lang; 2 | 3 | public class Class { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/Klass.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | public class Klass { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/Thread.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | public class Thread { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/VFrame.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | public class VFrame { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/memory/AllocateObj.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.memory; 2 | 3 | public class AllocateObj { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/memory/StackObj.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.memory; 2 | 3 | public class StackObj extends AllocateObj{ 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/memory/AllStatic.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.memory; 2 | 3 | public class AllStatic extends AllocateObj { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/memory/ResourceObj.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.memory; 2 | 3 | public class ResourceObj extends AllocateObj{ 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/sun/launcher/LauncherHelper.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes.sun.launcher; 2 | 3 | public class LauncherHelper { 4 | // test 5 | } 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/lambda/CustomLambda.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.lambda; 2 | 3 | 4 | @FunctionalInterface 5 | public interface CustomLambda { 6 | void run(); 7 | } 8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/lambda/CustomLambda1.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.lambda; 2 | 3 | 4 | @FunctionalInterface 5 | public interface CustomLambda1 { 6 | public void run(int x); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/lambda/CustomLambda2.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.lambda; 2 | 3 | 4 | @FunctionalInterface 5 | public interface CustomLambda2 { 6 | public void run(int x, int y); 7 | } 8 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | /compiler.xml 10 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/lambda/CustomLambdaParams.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.lambda; 2 | 3 | 4 | @FunctionalInterface 5 | public interface CustomLambdaParams { 6 | 7 | public void run(int x, int y); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/sun/misc/AppClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes.sun.misc; 2 | 3 | import com.cover.jvm.jdk.classes.Handle; 4 | 5 | public class AppClassLoader { 6 | public native static Handle loadKlass(String name); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/JavaThread.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Stack; 6 | 7 | @Data 8 | public class JavaThread extends Thread{ 9 | 10 | private Stack stack = new Stack<>(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/Annotation.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class Annotation { 7 | 8 | private int typeIndex; 9 | 10 | private int elementsNum; 11 | 12 | private String typeStr; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/sun/misc/Unsafe.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes.sun.misc; 2 | 3 | public class Unsafe { 4 | 5 | public static native long allocateMemory(long bytes); 6 | 7 | public static native long allocateObject(); 8 | 9 | public static native void initMemoryModel(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/BitCount.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class BitCount { 5 | 6 | public static void main(String[] args) { 7 | int v1 = 0x11; 8 | int v2 = 0xff; 9 | 10 | System.out.println(v1 & v2); 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/InstanceOf.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class InstanceOf { 5 | 6 | public static void main(String[] args) { 7 | InstanceOf obj = new InstanceOf(); 8 | 9 | System.out.println(obj instanceof InstanceOf); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Else.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Else { 5 | 6 | public static void main(String[] args) { 7 | int v1 = 10; 8 | int v2 = 20; 9 | int v3 = 30; 10 | 11 | System.out.println((v1 + v2) * v3); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/classfile/StackMapTable.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.classfile; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.oops.AttributeInfo; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class StackMapTable extends AttributeInfo { 8 | 9 | private int attrNameIndex; 10 | 11 | private int attrLength; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/Threads.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Threads { 6 | 7 | private static HashMap container = new HashMap<>(); 8 | 9 | public native static void createVM(); 10 | 11 | public native static void gc(); 12 | 13 | public native static void fullGc(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/FieldInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class FieldInfo { 7 | 8 | private int accessFlags; 9 | 10 | private int nameIndex; 11 | 12 | private int descriptorIndex; 13 | 14 | private int attributesCount; 15 | 16 | private CodeAttributeInfo[] attributes; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/utilities/AccessFlags.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.utilities; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class AccessFlags { 7 | 8 | private int flag; 9 | 10 | public AccessFlags(int flag) { 11 | this.flag = flag; 12 | } 13 | 14 | public boolean isStatic() { 15 | return (flag & BasicType.JVM_ACC_STATIC) != 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/AttributeInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class AttributeInfo { 7 | 8 | private int attrNameIndex; 9 | 10 | private int attrLength; 11 | 12 | // 用于存储klass的attribute 13 | private byte[] container; 14 | 15 | public void initContainer() { 16 | container = new byte[attrLength]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/InterfaceInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class InterfaceInfo { 7 | private int constantPoolIndex; 8 | 9 | private String interfaceName; 10 | 11 | public InterfaceInfo(int index, String name) { 12 | this.constantPoolIndex = index; 13 | 14 | this.interfaceName = name; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/RuntimeVisibleAnnotations.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class RuntimeVisibleAnnotations extends AttributeInfo { 10 | 11 | private int annotationsNum; 12 | 13 | private List annotations = new ArrayList<>(); 14 | 15 | private String attrName; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/RuntimeInvisibleAnnotations.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class RuntimeInvisibleAnnotations extends AttributeInfo { 10 | 11 | private int annotationsNum; 12 | 13 | private List annotations = new ArrayList<>(); 14 | 15 | private String attrName; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/sun/misc/ClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes.sun.misc; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.core.lang.Assert; 5 | 6 | import java.io.File; 7 | 8 | public class ClassLoader { 9 | 10 | public byte[] readFile(String filepath) { 11 | Assert.isNull(filepath); 12 | 13 | File file = new File(filepath); 14 | 15 | return FileUtil.readBytes(file); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang; 2 | 3 | public class HelloWorld { 4 | 5 | private static final int a = 1; 6 | 7 | private static final int b = 2; 8 | public static void main(String[] args) { 9 | System.out.println("Hello Wolrd!"); 10 | 11 | System.out.println(add(a, b)); 12 | } 13 | 14 | public static int add(int a, int b) { 15 | return a + b; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/SubSub.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class SubSub { 5 | 6 | public static void main(String[] args) { 7 | test1(); 8 | test2(); 9 | } 10 | 11 | public static void test1() { 12 | int v = 1; 13 | System.out.println(v--); 14 | } 15 | 16 | public static void test2() { 17 | int v = 1; 18 | System.out.println(--v); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/lambda/TestLambda.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.lambda; 2 | 3 | 4 | public class TestLambda { 5 | 6 | public static void main(String[] args) { 7 | CustomLambda2 obj = (x, y) -> { 8 | System.out.println("hello#" + x + "#" + y); 9 | }; 10 | 11 | obj.run(1, 2); 12 | 13 | //==== 14 | CustomLambda1 obj1 = (x) -> { 15 | System.out.println("hello#" + x); 16 | }; 17 | 18 | obj1.run(1); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/LineNumberTable.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class LineNumberTable extends AttributeInfo{ 7 | 8 | private int tableLength; 9 | 10 | private Item[] table; 11 | 12 | public void initTable() { 13 | table = new Item[tableLength]; 14 | } 15 | 16 | @Data 17 | public class Item { 18 | private int startPc; 19 | 20 | private int lineNumber; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/JniEnv.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes; 2 | 3 | 4 | /** 5 | * 生成java 头文件 6 | * 1. 进入到该目录 /home/ziya/IdeaProjects/XVM/src/main/java 7 | * 2.javac com/cover/jvm/jdk/classes/Handle.java 8 | * 3.javac -h /home/ziya/IdeaProjects/XVM/jni com/cover/jvm/jdk/classes/JniEnv.java 9 | * 10 | */ 11 | public class JniEnv { 12 | 13 | public native static Handle getMethodID(Handle klass, String name, String descriptorName); 14 | 15 | public native static void CallStaticVoidMethod(Handle klass, Handle method); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/interpreter/BytecodeStream.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.interpreter; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.oops.CodeAttributeInfo; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 5 | 6 | public class BytecodeStream extends BaseBytecodeStream{ 7 | 8 | public BytecodeStream(MethodInfo belongMethod, CodeAttributeInfo belongCode) { 9 | this.belongMethod = belongMethod; 10 | this.belongCode = belongCode; 11 | this.length = belongCode.getCodeLength(); 12 | this.index = 0; 13 | this.codes = new byte[this.length]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/compare/Integer.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.compare; 2 | 3 | 4 | public class Integer { 5 | 6 | public static void main(String[] args) { 7 | testLong(); 8 | } 9 | 10 | public static void test1() { 11 | byte v1 = 10; 12 | byte v2 = 20; 13 | 14 | System.out.println(v1 == v2); 15 | } 16 | 17 | public static void testLong() { 18 | long v1 = 10; 19 | long v2 = 20; 20 | 21 | System.out.println(v1 != v2); 22 | } 23 | 24 | public static void test() { 25 | Object obj = null; 26 | 27 | System.out.println(obj == null); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/LocalVariableTable.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class LocalVariableTable extends AttributeInfo{ 7 | 8 | private int tableLength; 9 | 10 | private Item[] table; 11 | 12 | public void initTable() { 13 | table = new Item[tableLength]; 14 | } 15 | 16 | @Data 17 | public class Item { 18 | private int startPc; 19 | 20 | private int length; 21 | 22 | private int nameIndex; 23 | 24 | private int descriptorIndex; 25 | 26 | private int index; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/array/Array.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.array; 2 | 3 | 4 | public class Array { 5 | 6 | public static void main(String[] args) { 7 | int[] arr; 8 | } 9 | 10 | public static void test1() { 11 | int[] arr = new int[3]; 12 | 13 | arr[0] = 10; 14 | 15 | System.out.println(arr[0]); 16 | } 17 | 18 | public static void test2() { 19 | int[] arr = {1, 2, 3}; 20 | 21 | System.out.println(arr[0]); 22 | } 23 | 24 | public static void test3() { 25 | Object[] objects = new Object[3]; 26 | 27 | objects[0] = new Array(); 28 | 29 | System.out.println(objects[0]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/condition/IfNull.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.condition; 2 | 3 | 4 | public class IfNull { 5 | 6 | public static void main(String[] args) { 7 | ifNonNull(); 8 | } 9 | 10 | public static void ifNull() { 11 | Object obj = null; 12 | 13 | if (null == obj) { 14 | System.out.println("null"); 15 | } else { 16 | System.out.println("not null"); 17 | } 18 | } 19 | 20 | public static void ifNonNull() { 21 | Object obj = null; 22 | 23 | if (null != obj) { 24 | System.out.println("null"); 25 | } else { 26 | System.out.println("not null"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/JavaVFrame.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class JavaVFrame extends VFrame { 8 | 9 | private StackValueCollection locals; 10 | 11 | private StackValueCollection stack = new StackValueCollection(); 12 | 13 | private MethodInfo ownerMethod; 14 | 15 | public JavaVFrame(int maxLocals) { 16 | locals = new StackValueCollection(maxLocals); 17 | } 18 | 19 | public JavaVFrame(int maxLocals, MethodInfo methodInfo) { 20 | locals = new StackValueCollection(maxLocals); 21 | ownerMethod = methodInfo; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/InnerClasses.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.utilities.AccessFlags; 4 | import lombok.Data; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class InnerClasses extends AttributeInfo { 11 | 12 | private String attrName; 13 | 14 | private int numOfClasses; 15 | 16 | private List classes = new ArrayList<>(); 17 | 18 | 19 | @Data 20 | public class Item { 21 | private int interClassInfoIndex; 22 | 23 | private int outerClassInfoIndex; 24 | 25 | private int innerNameIndex; 26 | 27 | private AccessFlags accessFlags; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/BootstrapMethods.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class BootstrapMethods extends AttributeInfo{ 10 | 11 | private String attrName; 12 | 13 | private int numBootstrapMethods; 14 | 15 | private List bootstrapMethods = new ArrayList<>(); 16 | 17 | @Data 18 | public class Item { 19 | private int bootstrapMethodRef; 20 | 21 | private int numBootstrapArguments; 22 | 23 | private int[] bootstrapArguments; 24 | 25 | public void initContainer() { 26 | bootstrapArguments = new int[numBootstrapArguments]; 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/jdk/classes/Handle.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.jdk.classes; 2 | 3 | public final class Handle { 4 | 5 | //oop/klass memory address 6 | private long p; 7 | 8 | /** 9 | * 1.klass 10 | * 2.oop 11 | * 3.method 12 | */ 13 | private int type; 14 | 15 | // 对应的Java类的全限定名 16 | private String className; 17 | 18 | public long getP() { 19 | return p; 20 | } 21 | 22 | public void setP(long p) { 23 | this.p = p; 24 | } 25 | 26 | public int getType() { 27 | return type; 28 | } 29 | 30 | public void setType(int type) { 31 | this.type = type; 32 | } 33 | 34 | public String getClassName() { 35 | return className; 36 | } 37 | 38 | public void setClassName(String className) { 39 | this.className = className; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/CodeAttributeInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.interpreter.BytecodeStream; 4 | import lombok.Data; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | @Data 10 | public class CodeAttributeInfo { 11 | private int attrNameIndex; 12 | 13 | private int attrLength; 14 | 15 | private int maxStack; 16 | 17 | private int maxLocals; 18 | 19 | private int codeLength; 20 | 21 | private BytecodeStream code; 22 | 23 | private int exceptionTableLength; 24 | 25 | // 如局部变量、操作数栈 26 | private int attributesCount; 27 | 28 | private Map attributes = new HashMap<>(); 29 | 30 | @Override 31 | public String toString() { 32 | return "CodeAttributeInfo{ }"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Div.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Div { 5 | 6 | public static void main(String[] args) { 7 | divInt(); 8 | divFloat(); 9 | divLong(); 10 | divDouble(); 11 | } 12 | 13 | public static void divInt() { 14 | int a = 4; 15 | int b = 2; 16 | 17 | System.out.println(a / b); 18 | } 19 | 20 | public static void divFloat() { 21 | float a = 4; 22 | float b = 2; 23 | 24 | System.out.println(a / b); 25 | } 26 | 27 | public static void divLong() { 28 | long a = 4; 29 | long b = 2; 30 | 31 | System.out.println(a / b); 32 | } 33 | 34 | public static void divDouble() { 35 | double a = 4; 36 | double b = 2; 37 | 38 | System.out.println(a / b); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Mul.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Mul { 5 | 6 | public static void main(String[] args) { 7 | mulInt(); 8 | mulFloat(); 9 | mulLong(); 10 | mulDouble(); 11 | } 12 | 13 | public static void mulInt() { 14 | int a = 1; 15 | int b = 2; 16 | 17 | System.out.println(a * b); 18 | } 19 | 20 | public static void mulFloat() { 21 | float a = 1; 22 | float b = 2; 23 | 24 | System.out.println(a * b); 25 | } 26 | 27 | public static void mulLong() { 28 | long a = 1; 29 | long b = 2; 30 | 31 | System.out.println(a * b); 32 | } 33 | 34 | public static void mulDouble() { 35 | double a = 1; 36 | double b = 2; 37 | 38 | System.out.println(a * b); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Rem.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Rem { 5 | 6 | public static void main(String[] args) { 7 | remInt(); 8 | remFloat(); 9 | remLong(); 10 | remDouble(); 11 | } 12 | 13 | public static void remInt() { 14 | int a = 1; 15 | int b = 2; 16 | 17 | System.out.println(a % b); 18 | } 19 | 20 | public static void remFloat() { 21 | float a = 1; 22 | float b = 2; 23 | 24 | System.out.println(a % b); 25 | } 26 | 27 | public static void remLong() { 28 | long a = 1; 29 | long b = 2; 30 | 31 | System.out.println(a % b); 32 | } 33 | 34 | public static void remDouble() { 35 | double a = 1; 36 | double b = 2; 37 | 38 | System.out.println(a % b); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Sub.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Sub { 5 | 6 | public static void main(String[] args) { 7 | subInt(); 8 | subFloat(); 9 | subLong(); 10 | subDouble(); 11 | } 12 | 13 | public static void subInt() { 14 | int a = 1; 15 | int b = 2; 16 | 17 | System.out.println(a - b); 18 | } 19 | 20 | public static void subFloat() { 21 | float a = 1; 22 | float b = 2; 23 | 24 | System.out.println(a - b); 25 | } 26 | 27 | public static void subLong() { 28 | long a = 1; 29 | long b = 2; 30 | 31 | System.out.println(a - b); 32 | } 33 | 34 | public static void subDouble() { 35 | double a = 1; 36 | double b = 2; 37 | 38 | System.out.println(a - b); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/Threads.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.memory.AllStatic; 4 | import lombok.Data; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class Threads extends AllStatic { 11 | 12 | 13 | /** 14 | * 所有的Java线程基本全部存储在这个list中 15 | */ 16 | private static List threadList; 17 | 18 | private static Thread currentThread; 19 | 20 | static { 21 | threadList = new ArrayList<>(); 22 | } 23 | 24 | public static List getThreadList() { 25 | return threadList; 26 | } 27 | 28 | public static JavaThread currentThread() { 29 | return (JavaThread) currentThread; 30 | } 31 | 32 | public static void setCurrentThread(Thread thread) { 33 | currentThread = thread; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/MethodInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.classfile.DescriptorStream2; 4 | import com.cover.jvm.hotspot.src.share.vm.utilities.AccessFlags; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class MethodInfo { 9 | 10 | private InstanceKlass belongKlass; 11 | 12 | private AccessFlags accessFlags; 13 | 14 | private int nameIndex; 15 | 16 | private int descriptorIndex; 17 | 18 | private int attributesCount; 19 | 20 | private CodeAttributeInfo[] attributes; 21 | 22 | private String methodName; 23 | 24 | private DescriptorStream2 descriptor; 25 | 26 | public void initAttributeContainer() { 27 | attributes = new CodeAttributeInfo[attributesCount]; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "MethodInfo{ }"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/DescriptorInfo.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DescriptorInfo { 7 | 8 | /** 9 | * 是否完成解析并赋值 10 | * 默认false 11 | */ 12 | private boolean isResolved = false; 13 | 14 | // 类型 15 | private int type; 16 | 17 | // 数组维度 18 | private int arrayDimension; 19 | 20 | // 类型 21 | private String typeDesc; 22 | 23 | public void incArrayDimension() { 24 | arrayDimension++; 25 | } 26 | 27 | public DescriptorInfo() { 28 | 29 | } 30 | 31 | public DescriptorInfo(boolean isResolved, int type) { 32 | this.isResolved = isResolved; 33 | this.type = type; 34 | } 35 | 36 | public DescriptorInfo(boolean isResolved, int type, String typeDesc) { 37 | this.isResolved = isResolved; 38 | this.type = type; 39 | this.typeDesc = typeDesc; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/condition/IfOther.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.condition; 2 | 3 | 4 | public class IfOther { 5 | 6 | public static void main(String[] args) { 7 | IntVSFloat(); 8 | } 9 | 10 | public static void floatCompare() { 11 | float f = 10; 12 | 13 | if (10 == f) { 14 | System.out.println("相等"); 15 | } else { 16 | System.out.println("不相等"); 17 | } 18 | 19 | if (f == 10) { 20 | System.out.println("相等"); 21 | } else { 22 | System.out.println("不相等"); 23 | } 24 | 25 | if (f > 10) { 26 | System.out.println("大于10"); 27 | } else { 28 | System.out.println("不大于10"); 29 | } 30 | } 31 | 32 | public static void IntVSFloat() { 33 | int i = 10; 34 | float f = 10; 35 | 36 | if (i == f) { 37 | System.out.println("相等"); 38 | } else { 39 | System.out.println("不相等"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/ArrayOop.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class ArrayOop { 10 | 11 | /** 12 | * 数组类型 13 | */ 14 | private int type; 15 | 16 | /** 17 | * 如果是引用类型数组,数组元素对应的类型 18 | */ 19 | private String className; 20 | 21 | /** 22 | * 数组大小 23 | */ 24 | private int size; 25 | 26 | private List data; 27 | 28 | public ArrayOop(int type, int size) { 29 | this.type = type; 30 | this.size = size; 31 | 32 | data = new ArrayList<>(size); 33 | } 34 | 35 | public ArrayOop(int type, String name, int size) { 36 | this.type = type; 37 | this.className = name; 38 | this.size = size; 39 | data = new ArrayList<>(size); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "ArrayOop{" + 45 | "type=" + type + 46 | ", size=" + size + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/Add.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class Add { 5 | 6 | public static void main(String[] args) { 7 | addInt(); 8 | addFloat(); 9 | addLong(); 10 | addDouble(); 11 | add(); 12 | } 13 | 14 | public static void addInt() { 15 | int a = 1; 16 | int b = 2; 17 | 18 | System.out.println(a + b); 19 | } 20 | 21 | public static void addFloat() { 22 | float a = 1; 23 | float b = 2; 24 | 25 | System.out.println(a + b); 26 | } 27 | 28 | public static void addLong() { 29 | long a = 1; 30 | long b = 2; 31 | 32 | System.out.println(a + b); 33 | } 34 | 35 | public static void addDouble() { 36 | double a = 1; 37 | double b = 2; 38 | 39 | System.out.println(a + b); 40 | } 41 | 42 | public static void add() { 43 | byte b = 1; 44 | char c = 2; 45 | short s = 3; 46 | int i = 4; 47 | long l = 5; 48 | 49 | System.out.println(b + c + s + i); 50 | } 51 | 52 | public static void test1() { 53 | byte b = 1; 54 | char c = 2; 55 | 56 | System.out.println(b + c); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/operation/AddAdd.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.operation; 2 | 3 | 4 | public class AddAdd { 5 | 6 | public static void main(String[] args) { 7 | byteAdd(); 8 | intAdd(); 9 | longAdd(); 10 | floatAdd(); 11 | doubleAdd(); 12 | doubleAdd2(); 13 | } 14 | 15 | public static void intAdd() { 16 | int v = 1; 17 | System.out.println(v++); 18 | System.out.println(++v); 19 | 20 | System.out.println(--v); 21 | } 22 | 23 | //===== 24 | public static void byteAdd() { 25 | byte v = 1; 26 | System.out.println(v++); 27 | System.out.println(++v); 28 | } 29 | 30 | public static void floatAdd() { 31 | float v = 1; 32 | System.out.println(v++); 33 | System.out.println(++v); 34 | } 35 | 36 | public static void longAdd() { 37 | long v = 1; 38 | System.out.println(v++); 39 | System.out.println(++v); 40 | } 41 | 42 | public static void doubleAdd() { 43 | double v = 1; 44 | System.out.println(v++); 45 | System.out.println(++v); 46 | } 47 | 48 | public static void doubleAdd2() { 49 | double v = 1; 50 | System.out.println(++v); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/InstanceKlass.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | @Data 11 | public class InstanceKlass extends Klass{ 12 | 13 | private byte[] magic = new byte[4]; 14 | 15 | private byte[] minorVersion = new byte[2]; 16 | 17 | private byte[] majorVersion = new byte[2]; 18 | 19 | private ConstantPool constantPool; 20 | 21 | private int accessFlag; 22 | 23 | private int thisClass; 24 | 25 | private int superClass; 26 | 27 | private int interfacesLength; 28 | 29 | private List interfaceInfos = new ArrayList<>(); 30 | 31 | private int fieldsLength; 32 | 33 | private List fields = new ArrayList<>(); 34 | 35 | private int methodLength; 36 | 37 | private MethodInfo[] methods; 38 | 39 | private int attributeLength; 40 | 41 | private Map attributeInfos = new HashMap<>(); 42 | 43 | public BootstrapMethods getBootstrapMethods() { 44 | return (BootstrapMethods)attributeInfos.get("BootstrapMethods"); 45 | } 46 | 47 | public InstanceKlass() { 48 | constantPool = new ConstantPool(); 49 | 50 | constantPool.setKlass(this); 51 | } 52 | 53 | public void initMethodsContainer() { 54 | methods = new MethodInfo[methodLength]; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "InstanceKlass{ }"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/Main.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.classfile.BootClassLoader; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.InstanceKlass; 5 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 6 | import com.cover.jvm.hotspot.src.share.vm.prims.JavaNativeInterface; 7 | import com.cover.jvm.hotspot.src.share.vm.runtime.JavaThread; 8 | import com.cover.jvm.hotspot.src.share.vm.runtime.Threads; 9 | import com.cover.jvm.jdk.classes.Handle; 10 | import com.cover.jvm.jdk.classes.JniEnv; 11 | import com.cover.jvm.jdk.classes.sun.misc.AppClassLoader; 12 | 13 | public class Main { 14 | public static void main(String[] args) { 15 | System.loadLibrary("jni"); 16 | com.cover.jvm.Threads.createVM(); 17 | // javaMain(); 18 | 19 | // 找到main方法所在的类 20 | Handle klassHandle = AppClassLoader.loadKlass("com/cover/jvm/example/java/lang/HelloWorld"); 21 | 22 | Handle methodHandle = JniEnv.getMethodID(klassHandle, "main", "([Ljava/lang/String;)V"); 23 | 24 | JniEnv.CallStaticVoidMethod(klassHandle, methodHandle); 25 | 26 | 27 | 28 | 29 | } 30 | 31 | public static void javaMain() { 32 | // 通过AppClassLoader加载main函数所在的类 33 | InstanceKlass mainKlass = BootClassLoader.loadMainKlass("com.cover.jvm.example.java.lang.lambda.TestLambda"); 34 | 35 | // 找到main方法 36 | MethodInfo mainMethod = JavaNativeInterface.getMethodID(mainKlass, "main", "([Ljava/lang/String;)V"); 37 | 38 | // 创建线程 39 | JavaThread thread = new JavaThread(); 40 | 41 | Threads.getThreadList().add(thread); 42 | Threads.setCurrentThread(thread); 43 | 44 | // 执行main方法 45 | JavaNativeInterface.callStaticMethod(mainMethod); 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/StackValue.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | import com.cover.jvm.hotspot.src.share.tools.DataTranslate; 4 | import com.cover.jvm.hotspot.src.share.vm.utilities.BasicType; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class StackValue { 9 | 10 | private int type; 11 | 12 | /** 13 | * 数据存储再这里的情况 14 | * 1.float 15 | */ 16 | private byte[] data; 17 | 18 | /** 19 | * 数据存储再这里的情况 20 | * 1.int 21 | * 2.short 22 | * 3.char 23 | * 4.byte 24 | * 5.double用两个int 25 | */ 26 | private int val; 27 | 28 | private Object object; 29 | 30 | public StackValue(int type, int val) { 31 | this.type = type; 32 | this.val = val; 33 | } 34 | 35 | public StackValue(int type, Object val) { 36 | this.type = type; 37 | this.object = val; 38 | } 39 | 40 | public StackValue(int type, float val) { 41 | this.type = type; 42 | this.data = DataTranslate.floatToByte(val); 43 | } 44 | 45 | public StackValue(int type, long v) { 46 | this.type = type; 47 | this.data = DataTranslate.longToBytes(v); 48 | } 49 | public Object getData() { 50 | switch (type) { 51 | case BasicType.T_OBJECT: 52 | return object; 53 | case BasicType.T_FLOAT: 54 | return DataTranslate.byteToFloat(data); 55 | case BasicType.T_LONG: 56 | return DataTranslate.bytesToLong(data); 57 | case BasicType.T_BYTE: 58 | case BasicType.T_INT: 59 | return val; 60 | case BasicType.T_ADDRESS: 61 | return DataTranslate.bytesToLong(data); 62 | } 63 | 64 | return null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/example/java/lang/condition/IfInt.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.example.java.lang.condition; 2 | 3 | 4 | public class IfInt { 5 | 6 | public static void main(String[] args) { 7 | ifeq(); 8 | ifne(); 9 | 10 | ifge(); 11 | ifgt(); 12 | 13 | ifle(); 14 | iflt(); 15 | } 16 | 17 | public static void ifeq() { 18 | int a = 0; 19 | 20 | if (a != 0) { 21 | System.out.println("不相等"); 22 | } else { 23 | System.out.println("相等"); 24 | } 25 | } 26 | 27 | public static void ifne() { 28 | int a = 0; 29 | 30 | if (a == 0) { 31 | System.out.println("相等"); 32 | } else { 33 | System.out.println("不相等"); 34 | } 35 | } 36 | 37 | public static void iflt() { 38 | int a = 0; 39 | 40 | if (a < 0) { 41 | System.out.println("a<0"); 42 | } else { 43 | System.out.println("a不<0"); 44 | } 45 | } 46 | 47 | public static void ifle() { 48 | int a = 0; 49 | 50 | if (a <= 0) { 51 | System.out.println("a<=0"); 52 | } else { 53 | System.out.println("a不<=0"); 54 | } 55 | } 56 | 57 | public static void ifgt() { 58 | int a = 0; 59 | 60 | if (a > 0) { 61 | System.out.println("a>0"); 62 | } else { 63 | System.out.println("a不>0"); 64 | } 65 | } 66 | 67 | public static void ifge() { 68 | int a = 0; 69 | 70 | if (a >= 0) { 71 | System.out.println("a>=0"); 72 | } else { 73 | System.out.println("a不>=0"); 74 | } 75 | } 76 | 77 | /** 78 | * 这两种写法生成的字节码不一样 79 | */ 80 | public static void test() { 81 | int a = 0; 82 | 83 | if (a == 0) { 84 | 85 | } 86 | 87 | if (0 == a) { 88 | 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cover.example 8 | XVM 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 8 13 | 8 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | com.beust 21 | jcommander 22 | 1.72 23 | 24 | 25 | 26 | cn.hutool 27 | hutool-all 28 | 5.5.9 29 | 30 | 31 | 32 | org.projectlombok 33 | lombok 34 | 1.18.8 35 | 36 | 37 | 38 | ch.qos.logback 39 | logback-core 40 | 1.2.3 41 | 42 | 43 | 44 | ch.qos.logback 45 | logback-classic 46 | 1.2.3 47 | 48 | 49 | 50 | ch.qos.logback 51 | logback-access 52 | 1.2.3 53 | 54 | 55 | 56 | cglib 57 | cglib 58 | 3.3.0 59 | 60 | 61 | 62 | javassist 63 | javassist 64 | 3.12.1.GA 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/interpreter/BaseBytecodeStream.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.interpreter; 2 | 3 | import com.cover.jvm.hotspot.src.share.tools.DataTranslate; 4 | import com.cover.jvm.hotspot.src.share.tools.Stream; 5 | import com.cover.jvm.hotspot.src.share.vm.memory.StackObj; 6 | import com.cover.jvm.hotspot.src.share.vm.oops.CodeAttributeInfo; 7 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 8 | import lombok.Data; 9 | 10 | import java.nio.ByteBuffer; 11 | import java.nio.ByteOrder; 12 | 13 | @Data 14 | public class BaseBytecodeStream extends StackObj { 15 | 16 | protected MethodInfo belongMethod; 17 | 18 | protected CodeAttributeInfo belongCode; 19 | 20 | protected int length; 21 | 22 | protected int index; 23 | 24 | protected byte[] codes; 25 | 26 | /** 27 | * 一次取一字节数据,自动累加 28 | * 29 | * @return 30 | */ 31 | public int getU1Code() { 32 | if (index < 0 || index >= length) { 33 | throw new Error("字节码指令的索引超过了最大值"); 34 | } 35 | return Byte.toUnsignedInt(codes[index++]); 36 | } 37 | 38 | public int getU1Code2() { 39 | if (index < 0 || index >= length) { 40 | throw new Error("字节码指令的索引超过了最大值"); 41 | } 42 | 43 | return codes[index++]; 44 | } 45 | 46 | public short getUnsignedShort() { 47 | if (index < 0 || index >= length) { 48 | throw new Error("字节码指令的索引超过了最大值"); 49 | } 50 | 51 | byte[] u2Arr = new byte[2]; 52 | 53 | Stream.readU2Simple(codes, index, u2Arr); 54 | index += 2; 55 | 56 | return (short) DataTranslate.byteToUnsignedShort(u2Arr); 57 | } 58 | 59 | public int getU4Code() { 60 | if (index < 0 || index >= length) { 61 | throw new Error("字节码指令的索引超过了最大值"); 62 | } 63 | 64 | byte[] arr = new byte[4]; 65 | 66 | Stream.readU4Simple(codes, index, arr); 67 | index += 4; 68 | ByteBuffer buffer = ByteBuffer.wrap(arr); 69 | 70 | buffer.order(ByteOrder.LITTLE_ENDIAN); 71 | 72 | return buffer.getInt(); 73 | } 74 | 75 | public void reset() { 76 | index = 0; 77 | } 78 | 79 | public boolean end() { 80 | return index >= length; 81 | } 82 | 83 | public void inc(int step) { 84 | index += step; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/classfile/BootClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.classfile; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.InstanceKlass; 5 | import lombok.Data; 6 | 7 | import java.io.File; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.regex.Pattern; 11 | 12 | @Data 13 | public class BootClassLoader { 14 | public static final String SUFFIX = ".class"; 15 | 16 | /** 17 | * 该类加载器的加载路径 18 | * 多个路径以分号分割 19 | * 只有一个的话,分号可以省略 20 | */ 21 | // FIXME 更换路径 22 | private static String searchPath = "/home/ziya/Documents/XVM/target/classes/"; 23 | 24 | /** 25 | * 用于存储该类加载器加载的所有类 26 | */ 27 | private static Map classLoaderData = new HashMap<>(); 28 | 29 | /** 30 | * main函数所在的类在此保存一份引用,方便快速定位到 31 | */ 32 | private static InstanceKlass mainKlass = null; 33 | 34 | public static InstanceKlass getMainKlass() { 35 | return mainKlass; 36 | } 37 | 38 | public static void setMainKlass(InstanceKlass mainKlass) { 39 | BootClassLoader.mainKlass = mainKlass; 40 | } 41 | 42 | public static InstanceKlass loadKlass(String name) { 43 | return loadKlass(name, true); 44 | } 45 | 46 | public static InstanceKlass loadKlass(String name, Boolean resolve) { 47 | InstanceKlass klass = findLoadedKlass(name); 48 | if (null != klass) { 49 | return klass; 50 | } 51 | 52 | klass = readAndParse(name); 53 | if (resolve) { 54 | resolveKlass(); 55 | } 56 | return klass; 57 | } 58 | 59 | private static InstanceKlass readAndParse(String name) { 60 | String tmpName = name.replace(".", "/"); 61 | String filePath = searchPath + tmpName + SUFFIX; 62 | 63 | // 读取字节码文件 64 | byte[] content = FileUtil.readBytes(new File(filePath)); 65 | 66 | // 解析字节码文件 67 | InstanceKlass klass = ClassFileParser.parseClassFile(null, content); 68 | // 存入 69 | classLoaderData.put(name, klass); 70 | return klass; 71 | } 72 | 73 | private static void resolveKlass() { 74 | 75 | } 76 | 77 | public static InstanceKlass findLoadedKlass(String name) { 78 | return classLoaderData.get(name); 79 | } 80 | 81 | public static InstanceKlass loadMainKlass(String name) { 82 | if (null != mainKlass) { 83 | return mainKlass; 84 | } 85 | 86 | return loadKlass(name); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/tools/Stream.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.tools; 2 | 3 | public class Stream { 4 | 5 | /** 6 | * 7 | * @param content 8 | * @param from 从哪个位置开始读 9 | * @param ret 传出参数 10 | * @return 读完之后指针的位置,即开始读的位置 + 读了多少 11 | */ 12 | public static int readU2(byte[] content, int from, byte[] ret) { 13 | System.arraycopy(content, from ,ret, 0, 2); 14 | return from + 2; 15 | } 16 | 17 | public static void readU2Simple(byte[] content, int from, byte[] ret) { 18 | System.arraycopy(content, from, ret, 0, 2); 19 | } 20 | 21 | public static void readSimple(byte[] content, int from, int size, byte[] ret) { 22 | System.arraycopy(content, from, ret, 0, size); 23 | } 24 | 25 | public static byte readU1Simple(byte[] content, int from) { 26 | byte[] arr = new byte[1]; 27 | System.arraycopy(content, from, arr, 0, 1); 28 | return arr[0]; 29 | } 30 | 31 | 32 | public static int readU4(byte[] content, int from, byte[] ret) { 33 | System.arraycopy(content, from, ret, 0 ,4); 34 | return from + 4; 35 | } 36 | 37 | public static void readU4Simple(byte[] content, int from, byte[] ret) { 38 | System.arraycopy(content, from,ret, 0, 4); 39 | } 40 | 41 | public static int readU1(byte[] content, int from, byte[] ret) { 42 | System.arraycopy(content, from, ret, 0, 1); 43 | return from + 1; 44 | } 45 | 46 | public static int readU8(byte[] content, int from, byte[] ret) { 47 | System.arraycopy(content, from ,ret, 0, 8); 48 | return from + 8; 49 | } 50 | 51 | public static void readU8Simple(byte[] content, int from, byte[] ret) { 52 | System.arraycopy(content, from, ret, 0 ,8); 53 | } 54 | 55 | public static String toHex(String s) { 56 | String str = ""; 57 | for (int i = 0; i < s.length(); i++) { 58 | int ch = (int)s.charAt(i); 59 | String s4 = Integer.toHexString(ch); 60 | str = str + s4; 61 | } 62 | 63 | return str; 64 | } 65 | 66 | public static int byteToUnsignedShort(byte[] bytes, int off) { 67 | int high = bytes[off]; 68 | int low = bytes[off + 1]; 69 | 70 | return (high << 8 & 0xFF00) | (low & 0xFF); 71 | } 72 | 73 | public static byte[] unsignedShortToByte(int s) { 74 | byte[] targets = new byte[2]; 75 | targets[0] = (byte) (s >> 8 & 0xFF); 76 | targets[1] = (byte) (s & 0xFF); 77 | return targets; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/utilities/BasicType.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.utilities; 2 | 3 | public class BasicType { 4 | 5 | // JVM 源码BasicType.java 6 | public static final int T_BOOLEAN = 4; 7 | 8 | public static final int T_CHAR = 5; 9 | 10 | public static final int T_FLOAT = 6; 11 | 12 | public static final int T_DOUBLE = 7; 13 | 14 | public static final int T_BYTE = 8; 15 | 16 | public static final int T_SHORT = 9; 17 | 18 | public static final int T_INT = 10; 19 | 20 | public static final int T_LONG = 11; 21 | 22 | public static final int T_OBJECT = 12; 23 | 24 | public static final int T_ARRAY = 13; 25 | 26 | public static final int T_VOID= 14; 27 | 28 | public static final int T_ADDRESS = 15; 29 | 30 | public static final int T_NARROWOOP = 16; 31 | 32 | public static final int T_METADATA = 17; 33 | 34 | public static final int T_NARROWKLASS = 18; 35 | 36 | public static final int T_CONFLICT = 19; 37 | 38 | public static final int T_ILLEGAL = 99; 39 | 40 | public static final int T_Throwable = 100; 41 | 42 | public static final int JVM_SIGNATURE_ARRAY = '['; 43 | 44 | public static final int JVM_SIGNATURE_BYTE = 'B'; 45 | 46 | public static final int JVM_SIGNATURE_CHAR = 'C'; 47 | 48 | public static final int JVM_SIGNATURE_CLASS = 'L'; 49 | 50 | public static final int JVM_SIGNATURE_ENDCLASS = ';'; 51 | 52 | public static final int JVM_SIGNATURE_ENUM = 'E'; 53 | 54 | public static final int JVM_SIGNATURE_FLOAT = 'F'; 55 | 56 | public static final int JVM_SIGNATURE_DOUBLE ='D'; 57 | 58 | public static final int JVM_SIGNATURE_FUNC = '('; 59 | 60 | public static final int JVM_SIGNATURE_ENDFUNC = ')'; 61 | 62 | public static final int JVM_SIGNATURE_INT = 'I'; 63 | 64 | public static final int JVM_SIGNATURE_LONG = 'J'; 65 | 66 | public static final int JVM_SIGNATURE_SHORT = 'S'; 67 | 68 | public static final int JVM_SIGNATURE_VOID = 'V'; 69 | 70 | public static final int JVM_SIGNATURE_BOOLEAN = 'Z'; 71 | 72 | // classfile_constant.h 73 | public static final int JVM_ACC_PUBLIC = 0x0001; 74 | 75 | public static final int JVM_ACC_PRIVATE = 0x0002; 76 | 77 | public static final int JVM_ACC_PROTECTED = 0x0004; 78 | 79 | public static final int JVM_ACC_STATIC = 0x0008; 80 | 81 | public static final int JVM_ACC_FINAL = 0x0010; 82 | 83 | public static final int JVM_ACC_SYNCHRONIZED = 0x0020; 84 | 85 | public static final int JVM_ACC_SUPER = 0x0020; 86 | 87 | public static final int JVM_ACC_VOLATILE = 0x0040; 88 | 89 | public static final int JVM_ACC_BRIDGE = 0x0040; 90 | 91 | public static final int JVM_ACC_TRANSIENT = 0x0080; 92 | 93 | public static final int JVM_ACC_VARARGS = 0x0080; 94 | 95 | public static final int JVM_ACC_NATIVE = 0x00100; 96 | 97 | public static final int JVM_ACC_INTERFACE = 0x00200; 98 | 99 | public static final int JVM_ACC_ABSTRACT = 0x00400; 100 | 101 | public static final int JVM_ACC_STRICT = 0x00800; 102 | 103 | public static final int JVM_ACC_SYNTHETIC = 0x001000; 104 | 105 | public static final int JVM_ACC_ANNOTATION = 0x002000; 106 | 107 | public static final int JVM_ACC_ENUM = 0x004000; 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/runtime/StackValueCollection.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.runtime; 2 | 3 | import com.cover.jvm.hotspot.src.share.tools.DataTranslate; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.ArrayOop; 5 | import com.cover.jvm.hotspot.src.share.vm.utilities.BasicType; 6 | import lombok.Data; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.nio.ByteBuffer; 11 | import java.nio.ByteOrder; 12 | import java.util.Stack; 13 | 14 | @Data 15 | public class StackValueCollection { 16 | 17 | private Logger logger = LoggerFactory.getLogger(StackValueCollection.class); 18 | 19 | /******************************** 20 | * 模拟操作数栈 21 | */ 22 | private Stack container = new Stack<>(); 23 | 24 | public StackValueCollection() { 25 | 26 | } 27 | 28 | public void push(StackValue value) { 29 | getContainer().push(value); 30 | } 31 | 32 | public StackValue pop() { 33 | return getContainer().pop(); 34 | } 35 | 36 | public StackValue peek() { 37 | return getContainer().peek(); 38 | } 39 | 40 | /** 41 | * 一个double用两个int存储 42 | * @param val 43 | */ 44 | public void pushDouble(double val) { 45 | byte[] bytes = DataTranslate.doubleToBytes(val); 46 | ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, 8); 47 | push(new StackValue(BasicType.T_DOUBLE, buffer.getInt(0))); 48 | // 为了后面取数据 49 | buffer.order(ByteOrder.LITTLE_ENDIAN); 50 | push(new StackValue(BasicType.T_DOUBLE, buffer.getInt(4))); 51 | 52 | } 53 | 54 | /** 55 | * 因为一个double占两个单元 56 | * 所以取的时候要连续取两个,并合并成double 57 | * @return 58 | */ 59 | public double popDouble() { 60 | ByteBuffer buffer = ByteBuffer.allocate(8); 61 | StackValue value1 = pop(); // 后4个字节 62 | StackValue value2 = pop(); // 前4个字节 63 | if (value1.getType() != BasicType.T_DOUBLE || value2.getType() != BasicType.T_DOUBLE) { 64 | throw new Error("类型检查不通过"); 65 | } 66 | 67 | buffer.putInt(value2.getVal(), value1.getVal()); 68 | return buffer.getDouble(); 69 | } 70 | 71 | public StackValue[] popDouble2() { 72 | StackValue[] ret = new StackValue[2]; 73 | ret[0] = pop(); 74 | ret[1] = pop(); 75 | return ret; 76 | } 77 | 78 | public void pushNull(JavaVFrame frame) { 79 | frame.getStack().push(new StackValue(BasicType.T_OBJECT, null)); 80 | } 81 | 82 | public void pushArray(ArrayOop array, JavaVFrame frame) { 83 | frame.getStack().push(new StackValue(BasicType.T_ARRAY, array)); 84 | } 85 | 86 | public ArrayOop popArray(JavaVFrame frame) { 87 | StackValue value = frame.getStack().pop(); 88 | if (BasicType.T_ARRAY != value.getType()) { 89 | throw new Error("类型检查不通过"); 90 | } 91 | 92 | return (ArrayOop) value.getObject(); 93 | } 94 | 95 | public void pushInt(int val, JavaVFrame frame) { 96 | frame.getStack().push(new StackValue(BasicType.T_INT, val)); 97 | } 98 | 99 | ////////////////////////////////////////模拟局部变量表 100 | private int maxLocals; 101 | 102 | private int index; 103 | 104 | private StackValue[] locals; 105 | 106 | public StackValueCollection(int size) { 107 | maxLocals = size; 108 | locals = new StackValue[size]; 109 | } 110 | 111 | public void smartAdd(int index, StackValue value) { 112 | getLocals()[index] = value; 113 | 114 | /** 115 | * 如果之前的index = 2 116 | * 这时候指定赋值了index = 5的位置,那后面就从6开始,而不会从3开始 117 | */ 118 | this.index += index; 119 | } 120 | 121 | public void add(int index, StackValue value) { 122 | getLocals()[index] = value; 123 | } 124 | 125 | public StackValue get(int index) { 126 | return getLocals()[index]; 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XVM(自己手写的Java VM) 2 | 手写JVM,为了目录比较清晰,该项目的目录结构是根据HotSpot的目录划分的,也是为了加深我们对HotSpot的理解 3 | ## 参考HotSpot版本1.8 4 | 源码下载链接: https://pan.baidu.com/s/158pDFPa2WYEVnJZ6qclxUw 提取码: 4p6f 5 | ## 主要模块 6 | HotSpot源码结构相当庞大,在该项目中并没有完完全全地实现其中每个功能,一方面由于语言限制,Java不像C++那样可以直接操作内存,其实也可以实现,不过实现起来需要更多的 7 | 模块结构去支撑这一体系,难度可想而知。 8 | ### 1.字节码文件解析器 9 | #### class文件组成 10 | ```java 11 | public class HelloWorld { 12 | 13 | private static final int a = 1; 14 | 15 | private static final int b = 2; 16 | public static void main(String[] args) { 17 | System.out.println("Hello Wolrd!"); 18 | 19 | System.out.println(add(a, b)); 20 | } 21 | 22 | public static int add(int a, int b) { 23 | return a + b; 24 | } 25 | } 26 | ``` 27 | 以HelloWorld代码为例,经过javac编译之后生成HelloWorld.class,那么我们怎么解析呢? 28 | ![img.png](img.png) 29 | 其实在class文件中,虚拟机是有自己的规范的,按照一定的顺序来存放的,顺序如下: 30 | ![img_1.png](img_1.png) 31 | 32 | + 1.魔数 4B(CAFE BABE) 33 | + 2.次版本号 2B 34 | + 3.主版本号 2B 35 | + 4.常量池大小 2B 36 | + 5.类的访问权限 2B 37 | + 6.类名 2B 38 | + 7.父类名 2B 39 | + 8.实现的接口个数2B、实现的接口 40 | + 9.属性数量2B、属性 41 | + 10.方法数量2B、方法 42 | 43 | 在HotSpot源码中,class字节码文件解析的过程在/hotspot/src/share/vm/classfile/classFileParser.cpp中的parseClassFile方法当中 44 | #### Java类在C++中的存储形式 45 | 根据上面的字节码组成结构,我们还需要知道一个Java对象在C++中的存在形式有哪些,进而在手写JVM的时候数据属性放在哪个对象之下。 46 | 在HotSpot的世界中,一个Java类对应着一个Klass模型的实例,其中 47 | + InstanceKlass是Java普通类的存在的C++形式,这个类是存储在方法区当中 48 | + InstanceMirrorKlass是Java类的Class对象,比如下面代码 49 | ```java 50 | Class helloWorld = HelloWorld.class; 51 | ``` 52 | InstanceMirrorKlass是存储在堆区中的C++实例,学名叫做镜相类 53 | 上面的分类是针对于非数组类型,那么对于数组类型来说, 54 | byte、boolean、char、short、int、float、long、double -> TypeArrayKlass 55 | 引用类型 -> ObjArrayKlass 56 | 57 | ![img_2.png](img_2.png) 58 | 59 | 60 | #### 常量池的解析 61 | 常量池项的数据类型 62 | ![img_3.png](img_3.png) 63 | 64 | 虚拟机规范当中的数据结构 65 | ![img_4.png](img_4.png) 66 | 67 | #### i++的实现底层 68 | ![img_7.png](img_7.png) 69 | ```java 70 | int i = 1; 71 | i++; 72 | ``` 73 | 操作步骤: 74 | 1.第一个操作数,拿到slot的index 75 | 2.第二个操作数,增加或减少的不长 76 | 3.完成运算 77 | 4.写回局部变量表 78 | 79 | 这个单独拿出来说,是因为觉得JVM的设计者的构思非常的巧妙,它的字节码对应的是iinc,这个字节码本身就是自增的意思,为什么还需要解释成iinc 1 by 1呢? 80 | 巧妙之处在于,如果想要实现i--这样的自减命令,或者i +=2时,这条iinc也可以使用,如果换作正常思维肯定是i++用一个字节码指令来实现,i--用一个字节码来实现, 81 | 一方面JVM的字节码指令只占1B,只能有255条指令,现如今已经使用了203条了. 82 | 83 | 通过上图我们还可以看到,slot的index在操作时只分配了一个字节,那也就是意味着说,局部变量表不能超过255个,不然就得拆成多个字节码指令来做,但是这样会影响JVM的执行效率。 84 | 那如果超过之后,JVM会怎么做呢? 85 | 在操作系统中,也存在着这样的问题,OS是对指令做了扩展,封装了一层二级指令,现在已经到了三级指令。 86 | 在这里我们也可以预测出,假如JVM以后要支持某种新特性的话,扩展字节码指令时,于是就出现了扩展指令. 87 | 88 | ### 2.数据类型的处理 89 | 我们知道在栈帧中小于等于4B的数据类型,是用一个插槽Slot来存储局部变量的,对于像Long、Double这样8B的数据类型,JVM是用两个Slot来表示,那么在字节码中,是被拆开了的。 90 | 而在我们当前的JVM中,则是合并在一起存储/读取的,只要不超过2的32次方-1这个数值,那么这样操作是没问题的。 91 | 注意:Linux 64位操作系统在操作原生栈的时候,CPU总是是以Word Size位单位(8B)字节从内存中进行读取/存储的,但是呢,JVM为了兼容32位机器,一直采用4B一个Slot 92 | 以后的话,这也是一个遗留问题,以后可能会出先最低版本兼容 93 | 94 | ### 3.方法的栈帧处理、流程控制 95 | 栈帧方面是用Java的Stack类型支持的,没有什么特殊处理的地方 96 | ### 4.支持lambda表达式 97 | #### 1.实现原理 98 | ![img_5.png](img_5.png) 99 | + 首先JVM会拿到常量池中的JVM_CONSTANT_InvokeDynamic信息,创建出Lambda的实现对象 100 | + 接着从常量池JVM_COSNTANT_InvokeDynamic中拿到BootstrapMethods的索引,即目前调用的是第几个BootstrapMethod 101 | + BootstrapMethod结构中的Bootstrap方法,对应的常量池项是MethodHandle,JVM就是通过LambdaMetafactory.metafactory创建出来CallSite,进而创建出Lambda表达式对应的对象的。 102 | BootstrapMethod结构中的其他信息,都是一些辅助信息,是调用metafactory方法需要传的参数 103 | ```java 104 | 105 | ``` 106 | + JVM也是通过执行LambdaMetafactory.metafactory完成Lambda表达式对应的函数式接口与具体实现中的代码的关联。背后的实现原理就是通过字节码 107 | + 默认的会在内存中生成一个新的类,并返回这个类的实例,所以可以这样调用方法 108 | ```java 109 | obj.run(1); 110 | ``` 111 | ![img_6.png](img_6.png) 112 | #### 2.Lambda表达式的实现主要依托三个东西 113 | + 1.匿名内部类 114 | + 2.invokedynamic 115 | + 3.MethodHandle 116 | #### 3.字节码角度看Lambda表达式 117 | + 1.常量池:JVM_Constant_InvokeDynamic_info、JVM_CONSTANT_MethodHandle(两个)、JVM_CONSTANT_MethodType 118 | + 2.类属性:BootstrapMethods 119 | #### 4.如何自实现呢? 120 | 我们最终的目的是想要生成一个MethodHandles.Lookup,一个类只会有一个Lookup 121 | ```java 122 | // 没有这样的API实现,我们需要用MethodHandle + 反射来实现 123 | MethodHandles.lookup(TestLambda.class); 124 | ``` 125 | 126 | 具体的实现请看com.cover.jvm.hotspot.src.share.vm.interpreter.LambdaEngine.createObject -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/prims/JavaNativeInterface.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.prims; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.interpreter.BytecodeInterpreter; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.CodeAttributeInfo; 5 | import com.cover.jvm.hotspot.src.share.vm.oops.InstanceKlass; 6 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 7 | import com.cover.jvm.hotspot.src.share.vm.runtime.JavaThread; 8 | import com.cover.jvm.hotspot.src.share.vm.runtime.JavaVFrame; 9 | import com.cover.jvm.hotspot.src.share.vm.runtime.Threads; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class JavaNativeInterface { 14 | 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(JavaNativeInterface.class); 17 | 18 | public static InstanceKlass findClass() { 19 | return null; 20 | } 21 | 22 | public static MethodInfo getMethodID(InstanceKlass klass, String name, String descriptorName) { 23 | MethodInfo[] methods = klass.getMethods(); 24 | for (MethodInfo method : methods) { 25 | String tmpName = (String) klass.getConstantPool().getDataMap().get(method.getNameIndex()); 26 | String tmpDescriptor = (String) klass.getConstantPool().getDataMap().get(method.getDescriptorIndex()); 27 | 28 | if (tmpName.equals(name) && tmpDescriptor.equals(descriptorName)) { 29 | logger.info("找到了方法: " + name + "#" + descriptorName); 30 | return method; 31 | } 32 | } 33 | logger.error("没有找到方法: " + name + "#" + descriptorName); 34 | 35 | return null; 36 | 37 | } 38 | 39 | public static void callStaticMethod(MethodInfo method) { 40 | JavaVFrame prevFrame = null; 41 | JavaThread thread = Threads.currentThread(); 42 | 43 | if (!method.getAccessFlags().isStatic()) { 44 | throw new Error("只能调用静态方法"); 45 | } 46 | 47 | /** 48 | * 需要获取上一个方法战阵的情况:需要传参 49 | */ 50 | if (0 != method.getDescriptor().getMethodParamsSize()) { 51 | 52 | /** 53 | * 取到上一个栈帧 54 | * 因为实参在这个栈帧中 55 | * 判断是为了过滤main方法 56 | */ 57 | if (0 != thread.getStack().size()) { 58 | logger.info("\t 从上一个栈帧取参数值"); 59 | prevFrame = (JavaVFrame) thread.getStack().peek(); 60 | 61 | } 62 | } else { 63 | logger.info("\t 方法 [" + method.getMethodName() + " ] 没有参数"); 64 | } 65 | 66 | CodeAttributeInfo codeAttributeInfo = method.getAttributes()[0]; 67 | 68 | // 创建栈帧 69 | JavaVFrame frame = new JavaVFrame(codeAttributeInfo.getMaxLocals(), method); 70 | 71 | if (null != prevFrame) { 72 | for (int i = 0; i < method.getDescriptor().getMethodParamsSize(); i++) { 73 | frame.getLocals().add(i, prevFrame.getStack().pop()); 74 | } 75 | } 76 | 77 | thread.getStack().push(frame); 78 | 79 | logger.info("第 " + thread.getStack().size() + " 个栈帧"); 80 | 81 | // 执行任务交给字节码解释器 82 | BytecodeInterpreter.run(thread, method); 83 | } 84 | 85 | public static void callMethod(MethodInfo method) { 86 | JavaVFrame prevFrame = null; 87 | JavaThread thread = Threads.currentThread(); 88 | 89 | /** 90 | * 需要获取上一个方法栈帧的情况: 91 | * 1.非静态方法。因为需要给this赋值 92 | * 2.需要传参 93 | */ 94 | 95 | if (!method.getAccessFlags().isStatic() || 0 != method.getDescriptor().getMethodParamsSize()) { 96 | /** 97 | * 取到上一个栈帧 98 | * 因为实参在这个栈帧中 99 | * 判断是为了过滤main方法 100 | */ 101 | if (0 != thread.getStack().size()) { 102 | logger.info("\t 从上一个栈帧取参数值"); 103 | 104 | prevFrame = (JavaVFrame)thread.getStack().peek(); 105 | } 106 | 107 | } else { 108 | logger.info("\t 方法 [ " + method.getMethodName() + " ] 没有参数"); 109 | } 110 | 111 | CodeAttributeInfo codeAttributeInfo = method.getAttributes()[0]; 112 | 113 | // 创建栈帧 114 | JavaVFrame frame = new JavaVFrame(codeAttributeInfo.getMaxLocals(), method); 115 | 116 | if (null != prevFrame) { 117 | /** 118 | * 如果是静态方法,从0开始 119 | * 如果是long、double,占用两个单元 120 | * 其他都占用一个单元 121 | * 如果是非静态方法,从1开始。0存放的是this 122 | * 如果是long、double,占用两个单元 123 | * 其他都占用一个单元 124 | */ 125 | if (method.getAccessFlags().isStatic()) { 126 | for (int i = 0; i < method.getDescriptor().getMethodParamsSize(); i++) { 127 | frame.getLocals().add(i, prevFrame.getStack().pop()); 128 | } 129 | } else { 130 | /** 131 | * 注意这里的顺序,如果是调用有参数的方法,压栈顺序 参数在上面 132 | * 133 | * | 参数 | 134 | * -------- 135 | * | 当前对象 | 给this赋值用 136 | */ 137 | for (int i = 1; i < method.getDescriptor().getMethodParamsSize() + 1; i++) { 138 | frame.getLocals().add(i, prevFrame.getStack().pop()); 139 | } 140 | 141 | // 给this赋值 142 | frame.getLocals().add(0, prevFrame.getStack().pop()); 143 | } 144 | 145 | } 146 | 147 | thread.getStack().push(frame); 148 | 149 | logger.info(" 第 " + thread.getStack().size() + " 个栈帧"); 150 | 151 | // 执行任务交给字节码解释器 152 | BytecodeInterpreter.run(thread, method); 153 | 154 | 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/classfile/DescriptorStream.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.classfile; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.memory.ResourceObj; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.DescriptorInfo; 5 | import com.cover.jvm.hotspot.src.share.vm.utilities.BasicType; 6 | import lombok.Data; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | public class DescriptorStream extends ResourceObj { 12 | 13 | private byte[] container; 14 | 15 | private DescriptorInfo info = new DescriptorInfo(); 16 | 17 | public DescriptorStream(String descriptor) { 18 | container = descriptor.getBytes(); 19 | } 20 | 21 | public DescriptorInfo parse() { 22 | for (int i = 0; i < container.length; i++) { 23 | byte b = container[i]; 24 | 25 | switch (b) { 26 | case '[': { 27 | String s = parseArrayType(); 28 | info.setType(BasicType.T_ARRAY); 29 | info.setTypeDesc(s); 30 | return info; 31 | } 32 | case 'L': { 33 | String s = parseReferenceType(); 34 | info.setType(BasicType.T_OBJECT); 35 | info.setTypeDesc(s); 36 | return info; 37 | } 38 | case 'Z': { // boolean 39 | info.setType(BasicType.T_BOOLEAN); 40 | return info; 41 | } 42 | case 'B': { // byte 43 | info.setType(BasicType.T_BYTE); 44 | return info; 45 | } 46 | case 'C': { // char 47 | info.setType(BasicType.T_CHAR); 48 | return info; 49 | } 50 | case 'I' : { // int 51 | info.setType(BasicType.T_INT); 52 | return info; 53 | } 54 | case 'F': { // float 55 | info.setType(BasicType.T_FLOAT); 56 | return info; 57 | } 58 | case 'J': { // long 59 | info.setType(BasicType.T_LONG); 60 | return info; 61 | } 62 | case 'D': { // double 63 | info.setType(BasicType.T_DOUBLE); 64 | return info; 65 | } 66 | case 'V': { 67 | info.setType(BasicType.T_VOID); 68 | return info; 69 | } 70 | default: 71 | throw new Error("无法识别的类型"); 72 | } /* end switch */ 73 | } 74 | return info; 75 | } 76 | 77 | private String parseArrayType() { 78 | for (int i = 0; i < container.length; i++) { 79 | // 取出数组维度 80 | if ('[' == container[i]) { 81 | info.incArrayDimension(); 82 | continue; 83 | } 84 | 85 | if ('L' != container[i]) { 86 | return null; 87 | } 88 | 89 | return parseArrReferenceType(); 90 | } 91 | 92 | return null; 93 | } 94 | 95 | private String parseArrReferenceType() { 96 | // 跳过数组维度个[、开头的L、结尾; 97 | int size = container.length - info.getArrayDimension() - 2; 98 | byte[] str = new byte[size]; 99 | 100 | // 跳过开头的L、结尾的; 101 | int j = 0; 102 | 103 | /** 104 | * 读的位置向后推移了info.getArrayDimension() + 1 105 | * 那就该多读这么多次 106 | */ 107 | for (int i = info.getArrayDimension() + 1; i < size + 1 + info.getArrayDimension(); i++) { 108 | str[j++] = container[i]; 109 | } 110 | 111 | return new String(str); 112 | } 113 | 114 | private String parseReferenceType() { 115 | // 跳过开头的L、结尾的 116 | int size = container.length - 2; 117 | byte[] str = new byte[size]; 118 | 119 | // 跳过开头的L、结尾的; 120 | int j = 0; 121 | for (int i = 1; i < container.length - 1; i++) { 122 | str[j++] = container[i]; 123 | } 124 | return new String(str); 125 | } 126 | 127 | public void parseParams(List infos) { 128 | for (int i = 0; i < container.length; i++) { 129 | byte b = container[i]; 130 | switch (b) { 131 | case 'Z': // boolean 132 | infos.add(new DescriptorInfo(true, BasicType.T_BOOLEAN)); 133 | break; 134 | case 'B': // byte 135 | infos.add(new DescriptorInfo(true, BasicType.T_BYTE)); 136 | break; 137 | case 'C': // char 138 | infos.add(new DescriptorInfo(true, BasicType.T_CHAR)); 139 | break; 140 | case 'I': // int 141 | infos.add(new DescriptorInfo(true, BasicType.T_INT)); 142 | break; 143 | case 'F': // float 144 | infos.add(new DescriptorInfo(true, BasicType.T_FLOAT)); 145 | break; 146 | case 'J': // long 147 | infos.add(new DescriptorInfo(true, BasicType.T_LONG)); 148 | break; 149 | case 'D': //double 150 | infos.add(new DescriptorInfo(true,BasicType.T_DOUBLE)); 151 | break; 152 | case 'V': 153 | infos.add(new DescriptorInfo(true, BasicType.T_VOID)); 154 | break; 155 | default: 156 | throw new Error("无法识别的类型"); 157 | } /* end switch */ 158 | } 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/oops/ConstantPool.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.oops; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | @Data 9 | public class ConstantPool { 10 | 11 | // classfile_constants.h 12 | public static final int JVM_CONSTANT_Utf8 = 1; 13 | 14 | public static final int JVM_CONSTANT_Unicode = 2; /* unused */ 15 | 16 | public static final int JVM_CONSTANT_Integer = 3; 17 | 18 | public static final int JVM_CONSTANT_Float = 4; 19 | 20 | public static final int JVM_CONSTANT_Long = 5; 21 | 22 | public static final int JVM_CONSTANT_Double = 6; 23 | 24 | public static final int JVM_CONSTANT_Class = 7; 25 | 26 | public static final int JVM_CONSTANT_String = 8; 27 | 28 | public static final int JVM_CONSTANT_Fieldref = 9; 29 | 30 | public static final int JVM_CONSTANT_Methodref = 10; 31 | 32 | public static final int JVM_CONSTANT_InterfaceMethodref = 11; 33 | 34 | public static final int JVM_CONSTANT_NameAndType = 12; 35 | 36 | public static final int JVM_CONSTANT_MethodHandle = 15; /* JSR 292 */ 37 | 38 | public static final int JVM_CONSTANT_MethodType = 16; /* JSR 292 */ 39 | 40 | public static final int JVM_CONSTANT_InvokeDynamic = 18; /* JSR 292 */ 41 | 42 | public static final int JVM_CONSTANT_ExternalMax = 18; /* Last tag found in classfiles */ 43 | 44 | private Klass klass; 45 | 46 | private int length; 47 | 48 | // index => type 49 | private int[] tag; 50 | 51 | // index => value 52 | private Map dataMap; 53 | 54 | public void initContainer() { 55 | tag = new int[length]; 56 | dataMap = new HashMap<>(length); 57 | } 58 | 59 | public String getClassName(int index) { 60 | if (0 == index || index > length) { 61 | return null; 62 | } 63 | 64 | /** 65 | * 解释: 66 | * 1.参数index对应的是JVM_CONSTANT_Class 67 | * 2.JVM_CONSTANT_Class中的信息才是类的全限定名在常量池中的索引 68 | */ 69 | return (String)getDataMap().get(getDataMap().get(index)); 70 | } 71 | 72 | public String getSuperClassName(int index) { 73 | if (0 == index || index > length) { 74 | return null; 75 | } 76 | 77 | /** 78 | * 解释: 79 | * 1.参数index对应的是JVM_CONSTANT_Class 80 | * 2.JVM_CONSTANT_Class中的信息才是类的全限定名在常量池中的索引 81 | */ 82 | return (String)getDataMap().get(index); 83 | } 84 | 85 | public String getMethodName(int index) { 86 | if (0 == index || index > length) { 87 | return null; 88 | } 89 | 90 | return (String)getDataMap().get(index); 91 | } 92 | 93 | public String getDescriptorName(int index) { 94 | if (0 == index || index > length) { 95 | return null; 96 | } 97 | 98 | return (String)getDataMap().get(index); 99 | } 100 | 101 | public String getClassNameByFieldInfo(int index) { 102 | // 获取CLass信息在常量池中的index 103 | int data = (int)getDataMap().get(index); 104 | int classIndex = data >> 16; 105 | 106 | // 获取Class全限定名的index 107 | int classNameIndex = (int)getDataMap().get(classIndex); 108 | 109 | return (String)getDataMap().get(classNameIndex); 110 | } 111 | 112 | public String getClassNameByMethodInfo(int index) { 113 | return getClassNameByFieldInfo(index); 114 | } 115 | 116 | public String getFieldName(int index) { 117 | // 获取NameAndType在常量池中的index 118 | int data = (int)getDataMap().get(index); 119 | int i = data & 0xFF; 120 | 121 | int nameAndType = (int)getDataMap().get(i); 122 | i = nameAndType >> 16; 123 | 124 | return (String)getDataMap().get(i); 125 | } 126 | 127 | public String getMethodNameByMethodInfo(int operand) { 128 | // 获取MethodInfo在常量池中的index 129 | int i = (int)getDataMap().get(operand); 130 | int nameAndTypeIndex = i & 0xff; 131 | 132 | // 获取NameAndType的值 133 | int data = (int)getDataMap().get(nameAndTypeIndex); 134 | i = data >> 16; 135 | return (String)getDataMap().get(i); 136 | } 137 | 138 | public String getDescriptorNameByMethodInfo(int operand) { 139 | // 获取MethodInfo在常量池中的index 140 | int i = (int)getDataMap().get(operand); 141 | int nameAndTypeIndex = i & 0xff; 142 | 143 | //获取NameAndType的值 144 | int data = (int)getDataMap().get(nameAndTypeIndex); 145 | i = data & 0xFF; 146 | return (String)getDataMap().get(i); 147 | } 148 | 149 | public int getBootMethodIndexByDynamicInfo(int operand) { 150 | int data = (int)getDataMap().get(operand); 151 | return data >> 16; 152 | } 153 | 154 | public String getMethodNameByDynamicInfo(int operand) { 155 | // 获取MethodInfo在常量池中的index 156 | int i = (int)getDataMap().get(operand); 157 | int nameAndTypeIndex = i & 0xff; 158 | 159 | // 获取NameAndTYpe的值 160 | int data = (int)getDataMap().get(nameAndTypeIndex); 161 | i = data >> 16; 162 | 163 | return (String)getDataMap().get(i); 164 | } 165 | 166 | public String getDescriptorNameByDynamicInfo(int operand) { 167 | // 获取MethodInfo在常量池中的index 168 | int i = (int)getDataMap().get(operand); 169 | int nameAndTypeIndex = i & 0xff; 170 | 171 | // 获取NameAndType的值 172 | int data = (int)getDataMap().get(nameAndTypeIndex); 173 | i = data & 0xff; 174 | return (String)getDataMap().get(i); 175 | } 176 | 177 | public String getClassNameByMethodHandleInfo(int operand) { 178 | int i = (int)getDataMap().get(operand); 179 | int methodrefInfoIndex = i & 0xFF; 180 | return getClassNameByMethodInfo(methodrefInfoIndex); 181 | } 182 | 183 | public String getMethodNameByMethodHandleInfo(int operand) { 184 | int i = (int)getDataMap().get(operand); 185 | int methodrefInfoIndex = i & 0xFF; 186 | 187 | return getMethodNameByMethodInfo(methodrefInfoIndex); 188 | } 189 | 190 | public String getDescriptorNameByMethodHandleInfo(int operand) { 191 | int i = (int)getDataMap().get(operand); 192 | int methodrefInfoIndex = i & 0xFF; 193 | 194 | return getDescriptorNameByMethodInfo(methodrefInfoIndex); 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/tools/DataTranslate.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.tools; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.ByteOrder; 5 | 6 | public class DataTranslate { 7 | 8 | private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 9 | 10 | public static String bytesToHexFun1(byte[] bytes) { 11 | char[] buf = new char[bytes.length * 2]; 12 | int a = 0; 13 | int index = 0; 14 | for (byte b : bytes) { 15 | if (b < 0) { 16 | a = 256 + b; 17 | } else { 18 | a = b; 19 | } 20 | 21 | buf[index++] = HEX_CHAR[a / 16]; 22 | buf[index++] = HEX_CHAR[a % 16]; 23 | } 24 | return new String(buf); 25 | } 26 | 27 | public static String bytesTOHexFun2(byte[] bytes) { 28 | char[] buf = new char[bytes.length * 2]; 29 | int index = 0; 30 | 31 | for (byte b : bytes) { 32 | buf[index++] = HEX_CHAR[b >>> 4 & 0xf]; 33 | buf[index++] = HEX_CHAR[b & 0xf]; 34 | } 35 | 36 | return new String(buf); 37 | } 38 | 39 | public static String bytesToHexFun3(byte[] bytes) { 40 | StringBuilder buf = new StringBuilder(bytes.length * 2); 41 | for (byte b : bytes) { 42 | buf.append(String.format("%02x", new Integer(b & 0xff))); 43 | } 44 | return buf.toString(); 45 | } 46 | 47 | public static byte[] toBytes(String str) { 48 | if (str == null || str.trim().equals("")) { 49 | return new byte[0]; 50 | } 51 | 52 | byte[] bytes = new byte[str.length() / 2]; 53 | for (int i = 0; i < str.length() / 2; i++) { 54 | String subStr = str.substring( i * 2, i * 2 + 2); 55 | bytes[i] = (byte) Integer.parseInt(subStr, 16); 56 | } 57 | 58 | return bytes; 59 | } 60 | 61 | public static int byteToUnsignedShort(byte[] bytes) { 62 | int high = bytes[0]; 63 | int low = bytes[1]; 64 | return (high << 8 & 0xFF00) | (low & 0xFF); 65 | } 66 | 67 | public static byte[] unsignedShortToByte(int s) { 68 | byte[] targets = new byte[2]; 69 | targets[0] = (byte) (s >> 8 & 0xFF); 70 | targets[1] = (byte)(s & 0xFF); 71 | return targets; 72 | } 73 | 74 | /** 75 | * int到byte[] 由高位到低位 76 | * @param i 需要转换为byte数组的整行值 77 | * @return byte数组 78 | */ 79 | public static byte[] intToByteArray(int i) { 80 | byte[] result = new byte[4]; 81 | result[0] = (byte) ((i >> 24) & 0xFF); 82 | result[1] = (byte) ((i >> 16) & 0xFF); 83 | result[2] = (byte) ((i >> 8) & 0xFF); 84 | result[3] = (byte) (i & 0xFF); 85 | 86 | return result; 87 | } 88 | 89 | /** 90 | * byte[]转int 91 | */ 92 | public static int byteArrayToInt(byte[] bytes) { 93 | int value = 0; 94 | for (int i = 0; i < 4; i++) { 95 | int shift = (3 -i) * 8; 96 | value += (bytes[i] & 0xFF) << shift; 97 | } 98 | 99 | return value; 100 | } 101 | 102 | public static float byteToFloat(byte[] b) { 103 | int l; 104 | l = b[3]; 105 | l &= 0xff; 106 | l |= ((long)b[2] << 8); 107 | l &= 0xffff; 108 | l |= ((long)b[1] << 16); 109 | l &= 0xffffff; 110 | l |= ((long) b[0] << 24); 111 | return Float.intBitsToFloat(l); 112 | } 113 | 114 | public static float bytesToFloat(byte[] arr, boolean littleEndian) { 115 | ByteBuffer buffer = ByteBuffer.wrap(arr, 0 ,4); 116 | if (littleEndian) { 117 | buffer.order(ByteOrder.LITTLE_ENDIAN); 118 | } 119 | 120 | return buffer.getFloat(); 121 | } 122 | 123 | public static byte[] floatToByte(float f) { 124 | byte[] ret = new byte[4]; 125 | // 将float里面的二进制串解释为int整数 126 | int i = Float.floatToIntBits(f); 127 | ret[0] = (byte) ((i & 0xff000000) >> 24); 128 | ret[1] = (byte) ((i & 0x00ff0000) >> 16); 129 | ret[2] = (byte) ((i & 0x0000ff00) >> 8); 130 | ret[3] = (byte) (i & 0x000000ff); 131 | return ret; 132 | } 133 | 134 | public static Long byteToLong(byte[] input, int offset, boolean littleEndian) { 135 | long value = 0; 136 | // 循环读取每个字节通过移位运算完成long的8个字节拼接 137 | for (int count = 0; count < 8; ++count) { 138 | int shift = (littleEndian ? count : (7 - count)) << 3; 139 | value |= ((long)0xff << shift) & ((long)input[offset + count] << shift); 140 | } 141 | 142 | return value; 143 | } 144 | 145 | public static long bytes2long(byte[] bs) throws Exception { 146 | int bytes = bs.length; 147 | if (bytes > 1) { 148 | if ((bytes % 2) != 0 || bytes > 8) { 149 | throw new Exception("not support"); 150 | } 151 | } 152 | switch (bytes) { 153 | case 0: 154 | return 0; 155 | case 1: 156 | return (long)((bs[0] & 0xff)); 157 | case 2: 158 | return (long)((bs[0] & 0xff) << 8 | (bs[1] & 0xff)); 159 | case 4: 160 | return (long)((bs[0] & 0xffL) << 24 | (bs[1] & 0xffL) << 16 | (bs[2] & 0xffL) << 8 | (bs[3] & 0xffL)); 161 | case 8: 162 | return (long)((bs[0] & 0xffL) << 56 | (bs[1] & 0xffL) << 48 | (bs[2] & 0xffL) << 40 | (bs[3] & 0xffL) << 32 163 | | (bs[4] & 0xffL) << 24 | (bs[5] & 0xffL) << 16 | (bs[6] & 0xffL) << 8 | (bs[7] & 0xffL)); 164 | default: 165 | throw new Exception("not support"); 166 | } 167 | } 168 | 169 | /** 170 | * 是否是小端模式 171 | */ 172 | public static double bytesToDouble(byte[] arr, boolean littleEndian) { 173 | ByteBuffer buffer = ByteBuffer.wrap(arr, 0, 8); 174 | if (littleEndian) { 175 | buffer.order(ByteOrder.LITTLE_ENDIAN); 176 | } 177 | return buffer.getDouble(); 178 | } 179 | 180 | public static byte[] doubleToBytes(double d) { 181 | long value = Double.doubleToRawLongBits(d); 182 | byte[] byteRet = new byte[8]; 183 | for (int i = 0; i < 8; i++) { 184 | byteRet[i] = (byte)((value >> 8 * i) & 0xff); 185 | } 186 | 187 | return byteRet; 188 | } 189 | 190 | public static byte[] longToBytes(long v) { 191 | ByteBuffer buffer = ByteBuffer.allocate(8); 192 | buffer.putLong(v); 193 | return buffer.array(); 194 | } 195 | 196 | public static long bytesToLong(byte[] arr) { 197 | ByteBuffer buffer = ByteBuffer.wrap(arr, 0, 8); 198 | return buffer.getLong(); 199 | } 200 | 201 | 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/interpreter/LambdaEngine.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.interpreter; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.classfile.DescriptorStream2; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.AttributeInfo; 5 | import com.cover.jvm.hotspot.src.share.vm.oops.BootstrapMethods; 6 | import com.cover.jvm.hotspot.src.share.vm.oops.MethodInfo; 7 | 8 | import java.lang.invoke.*; 9 | import java.lang.reflect.Field; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | 13 | public class LambdaEngine { 14 | 15 | private MethodInfo method; 16 | 17 | private int index; 18 | 19 | public LambdaEngine(MethodInfo method, int index) { 20 | this.method = method; 21 | this.index = index; 22 | } 23 | 24 | public Object createObject() { 25 | /** 26 | * 获取常量池项JVM_CONSTANT_InvokeDynamic中的信息 run 27 | */ 28 | String sourceMethodName = method.getBelongKlass().getConstantPool().getMethodNameByDynamicInfo(index); 29 | 30 | // 动态创建的对象类型() Lcom/cover/jvm/example/java/lang/lambda/CustomLambda; 31 | String descriptorName = method.getBelongKlass().getConstantPool().getDescriptorNameByDynamicInfo(index); 32 | 33 | DescriptorStream2 descriptorStream = new DescriptorStream2(descriptorName); 34 | 35 | descriptorStream.parseMethod(); 36 | 37 | // BootstrapMethods中的index,即当前lambda表达爱是对应的是第几个BootstrapMethod; 38 | int bootMethodIndex = method.getBelongKlass().getConstantPool().getBootMethodIndexByDynamicInfo(index); 39 | 40 | // ==== 41 | BootstrapMethods bootstrapMethods = (BootstrapMethods) method.getBelongKlass().getAttributeInfos().get("BootstrapMethods"); 42 | 43 | BootstrapMethods.Item item = bootstrapMethods.getBootstrapMethods().get(bootMethodIndex); 44 | int methodHandleIndex = item.getBootstrapArguments()[1]; 45 | 46 | // ==== 47 | String className = method.getBelongKlass().getConstantPool().getClassNameByMethodHandleInfo(methodHandleIndex); 48 | String lambdaMethodName = method.getBelongKlass().getConstantPool().getMethodNameByMethodHandleInfo(methodHandleIndex); 49 | String lambdaDescriptorName = method.getBelongKlass().getConstantPool().getDescriptorNameByMethodHandleInfo(methodHandleIndex); 50 | 51 | DescriptorStream2 lambdaDescriptorStream = new DescriptorStream2(lambdaDescriptorName); 52 | lambdaDescriptorStream.parseMethod(); 53 | 54 | Class[] paramsClass = lambdaDescriptorStream.getParamsType(); 55 | 56 | // ==== 57 | try { 58 | Class returnClazz = Class.forName(descriptorStream.getReturnElement().getTypeDesc().replace('/', '.')); 59 | Class callerClazz = Class.forName(className.replace('/', '.')); 60 | 61 | MethodHandles.Lookup lookup = getLookup(callerClazz); 62 | System.out.println("\t 创建MethodHandles.Lookup"); 63 | 64 | Method method = callerClazz.getDeclaredMethod(lambdaMethodName, paramsClass); 65 | MethodHandle unreflect = lookup.unreflect(method); 66 | 67 | MethodType type = unreflect.type(); 68 | MethodType factoryType = MethodType.methodType(returnClazz); 69 | CallSite callSite = LambdaMetafactory.metafactory(lookup, sourceMethodName, factoryType, type, unreflect, type); 70 | 71 | System.out.println("\t 创建dynamic call site"); 72 | 73 | MethodHandle target = callSite.getTarget(); 74 | 75 | System.out.println("\t 创建Lambda对象"); 76 | return target.invoke(); 77 | } catch (ClassNotFoundException e) { 78 | throw new RuntimeException(e); 79 | } catch (Exception e) { 80 | throw new RuntimeException(e); 81 | } catch (Throwable e) { 82 | throw new RuntimeException(e); 83 | } 84 | } 85 | 86 | 87 | /** 88 | * 完成运行 89 | */ 90 | public void run() { 91 | /** 92 | * 获取常量池项JVM_CONSTANT_InvokeDynamic中的信息 93 | */ 94 | String sourceMethodName = method.getBelongKlass().getConstantPool().getMethodNameByDynamicInfo(index); 95 | // 动态创建的对象类型 96 | String descriptorName = method.getBelongKlass().getConstantPool().getDescriptorNameByDynamicInfo(index); 97 | 98 | DescriptorStream2 descriptorStream = new DescriptorStream2(descriptorName); 99 | descriptorStream.parseMethod(); 100 | 101 | // BootstrapMethods中的index,即当前lambda表达式对应的第几个BootstrapMethod 102 | int bootMethodIndex = method.getBelongKlass().getConstantPool().getBootMethodIndexByDynamicInfo(index); 103 | 104 | // ==== 105 | BootstrapMethods bootstrapMethods = (BootstrapMethods)method.getBelongKlass().getAttributeInfos().get("BootstrapMethods"); 106 | 107 | BootstrapMethods.Item item = bootstrapMethods.getBootstrapMethods().get(bootMethodIndex); 108 | int methodHandleIndex = item.getBootstrapArguments()[1]; 109 | 110 | // ==== 111 | String className = method.getBelongKlass().getConstantPool().getClassNameByMethodHandleInfo(methodHandleIndex); 112 | String lambdaMethodName = method.getBelongKlass().getConstantPool().getMethodNameByMethodHandleInfo(methodHandleIndex); 113 | String lambdaDescriptorName = method.getBelongKlass().getConstantPool().getDescriptorNameByMethodHandleInfo(methodHandleIndex); 114 | 115 | DescriptorStream2 lambdaDescriptorStream = new DescriptorStream2(lambdaDescriptorName); 116 | lambdaDescriptorStream.parseMethod();; 117 | 118 | Class[] paramsClass = lambdaDescriptorStream.getParamsType(); 119 | // ==== 120 | 121 | try { 122 | Class returnClazz = Class.forName(descriptorStream.getReturnElement().getTypeDesc().replace('/', '.')); 123 | Class callerClazz = Class.forName(className.replace('/', '.')); 124 | 125 | MethodHandles.Lookup lookup = getLookup(callerClazz); 126 | 127 | Method method = callerClazz.getDeclaredMethod(lambdaMethodName, paramsClass); 128 | 129 | MethodHandle unreflect = lookup.unreflect(method); 130 | MethodType type = unreflect.type(); 131 | 132 | MethodType factoryType = MethodType.methodType(returnClazz); 133 | CallSite callSite = LambdaMetafactory.metafactory(lookup, sourceMethodName, factoryType, type, unreflect, type); 134 | 135 | MethodHandle target = callSite.getTarget(); 136 | 137 | Method callMethod = returnClazz.getDeclaredMethod(sourceMethodName, paramsClass); 138 | callMethod.invoke(target.invoke()); 139 | 140 | // 无参数,这样调用也可以 141 | // MethodHandle methodHandle = lookup.findVirtual(returnClazz, sourceMethodName, MethodType.methodType(void.class)); 142 | // methodHandle.invoke(target.invoke()); 143 | 144 | } catch (ClassNotFoundException e) { 145 | throw new RuntimeException(e); 146 | } catch (Exception e) { 147 | throw new RuntimeException(e); 148 | } catch (Throwable e) { 149 | throw new RuntimeException(e); 150 | } 151 | System.exit(-1); 152 | } 153 | 154 | 155 | private MethodHandles.Lookup getLookup(Class callerClazz) throws Exception { 156 | Class c = Class.forName(MethodHandles.Lookup.class.getName()); 157 | Field implLookup = c.getDeclaredField("IMPL_LOOKUP"); 158 | implLookup.setAccessible(true); 159 | 160 | Object o = implLookup.get(MethodHandles.Lookup.class); 161 | 162 | Method method = c.getDeclaredMethod("in", Class.class); 163 | 164 | return (MethodHandles.Lookup) method.invoke(o, callerClazz); 165 | } 166 | 167 | 168 | } 169 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/classfile/DescriptorStream2.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.classfile; 2 | 3 | import com.cover.jvm.hotspot.src.share.vm.memory.ResourceObj; 4 | import com.cover.jvm.hotspot.src.share.vm.oops.DescriptorInfo; 5 | import com.cover.jvm.hotspot.src.share.vm.runtime.JavaVFrame; 6 | import com.cover.jvm.hotspot.src.share.vm.runtime.StackValue; 7 | import com.cover.jvm.hotspot.src.share.vm.utilities.BasicType; 8 | import lombok.Data; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @Data 14 | public class DescriptorStream2 extends ResourceObj { 15 | 16 | private String descriptor; 17 | 18 | private DescriptorInfo returnElement; 19 | 20 | private int methodParamsSize; 21 | 22 | private List parameters = new ArrayList<>(); 23 | 24 | public DescriptorStream2(String descriptor) { 25 | this.descriptor = descriptor; 26 | } 27 | 28 | 29 | public void parseMethod() { 30 | parseMethodParams(); 31 | parseReturn(); 32 | } 33 | 34 | public void parseField() { 35 | returnElement = new DescriptorStream(descriptor).parse(); 36 | } 37 | 38 | public DescriptorInfo parseReturn() { 39 | int paramEndIndex = descriptor.indexOf(")"); 40 | String returnStr = descriptor.substring(paramEndIndex + 1, descriptor.length()); 41 | returnElement = new DescriptorStream(returnStr).parse(); 42 | return returnElement; 43 | } 44 | 45 | public List parseMethodParams() { 46 | int paramStartIndex = descriptor.indexOf('('); 47 | int paramEndIndex = descriptor.indexOf(')'); 48 | 49 | String paramStr = descriptor.substring(paramStartIndex + 1, paramEndIndex); 50 | String[] strings = paramStr.split(";"); 51 | if (strings.length > 0) { 52 | for (int i = 0; i < strings.length; i++) { 53 | String s = strings[i]; 54 | 55 | // 处理字符串或数组 56 | if (s.startsWith("L") || s.startsWith("[")) { 57 | // 保持格式。 共用解析返回值的程序 58 | s += ";"; 59 | 60 | parameters.add(new DescriptorStream(s).parse()); 61 | 62 | continue; 63 | } 64 | 65 | // 处理其他 66 | new DescriptorStream(s).parseParams(parameters); 67 | } 68 | } 69 | 70 | setMethodParamsSize(parameters.size()); 71 | return parameters; 72 | } 73 | 74 | 75 | public Class[] getParamsType() { 76 | Class[] types = new Class[getMethodParamsSize()]; 77 | for (int i = 0; i < getMethodParamsSize(); i++) { 78 | DescriptorInfo info = getParameters().get(i); 79 | switch (info.getType()) { 80 | case BasicType.T_BOOLEAN: 81 | types[i] = boolean.class; 82 | break; 83 | case BasicType.T_CHAR: 84 | types[i] = char.class; 85 | break; 86 | case BasicType.T_INT: 87 | types[i] = int.class; 88 | break; 89 | case BasicType.T_OBJECT: 90 | try { 91 | types[i] = Class.forName(info.getTypeDesc().replace("/", ".")); 92 | } catch (ClassNotFoundException e) { 93 | throw new RuntimeException(e); 94 | } 95 | break; 96 | case BasicType.T_LONG: 97 | types[i] = long.class; 98 | break; 99 | case BasicType.T_DOUBLE: 100 | types[i] = double.class; 101 | break; 102 | case BasicType.T_FLOAT: 103 | types[i] = float.class; 104 | break; 105 | case BasicType.T_ARRAY: 106 | throw new Error("数组类型,未作处理"); 107 | default: 108 | throw new Error("无法识别的参数类型"); 109 | } 110 | 111 | } 112 | 113 | return types; 114 | } 115 | 116 | public Object[] getParamsVal(JavaVFrame frame) { 117 | Object[] vals = new Object[getMethodParamsSize()]; 118 | for (int i = 0; i < getMethodParamsSize(); i++) { 119 | DescriptorInfo info = getParameters().get(i); 120 | 121 | switch (info.getType()) { 122 | case BasicType.T_BOOLEAN: 123 | int val = frame.getStack().pop().getVal(); 124 | vals[i] = (1 == val) ? true: false; 125 | 126 | break; 127 | case BasicType.T_CHAR: 128 | /** 129 | * 这里一定要强转 130 | * 否则接受的参数是char,传int会报错 131 | */ 132 | vals[i] = (char)frame.getStack().pop().getVal(); 133 | break; 134 | case BasicType.T_INT: 135 | vals[i] = frame.getStack().pop().getVal(); 136 | break; 137 | case BasicType.T_OBJECT: 138 | vals[i] = frame.getStack().pop().getObject(); 139 | break; 140 | case BasicType.T_LONG: 141 | vals[i] = frame.getStack().pop().getData(); 142 | break; 143 | case BasicType.T_DOUBLE: 144 | vals[i] = frame.getStack().popDouble(); 145 | break; 146 | case BasicType.T_FLOAT: 147 | vals[i] = frame.getStack().pop().getData(); 148 | break; 149 | case BasicType.T_ARRAY: 150 | throw new Error("数组类型, 未作处理"); 151 | default: 152 | throw new Error("无法识别的参数类型"); 153 | } 154 | } 155 | 156 | return vals; 157 | } 158 | 159 | public Class getFieldType() { 160 | Class type = null; 161 | switch (returnElement.getType()) { 162 | case BasicType.T_CHAR: 163 | type = char.class; 164 | break; 165 | case BasicType.T_INT: 166 | type = int.class; 167 | break; 168 | case BasicType.T_OBJECT: 169 | 170 | try { 171 | type = Class.forName(returnElement.getTypeDesc().replace('/', '.')); 172 | } catch (ClassNotFoundException e) { 173 | e.printStackTrace(); 174 | } 175 | break; 176 | case BasicType.T_LONG: 177 | type = long.class; 178 | break; 179 | case BasicType.T_DOUBLE: 180 | type = double.class; 181 | break; 182 | case BasicType.T_ARRAY: 183 | throw new Error("数组类型,未作处理"); 184 | default: 185 | throw new Error("无法识别的参数类型"); 186 | } 187 | 188 | return type; 189 | } 190 | 191 | public Object getFieldVal(JavaVFrame frame) { 192 | Object val = null; 193 | 194 | switch (returnElement.getType()) { 195 | case BasicType.T_CHAR: { 196 | val = frame.getStack().pop().getVal(); 197 | 198 | break; 199 | } 200 | case BasicType.T_INT: { 201 | val = frame.getStack().pop().getVal(); 202 | 203 | break; 204 | } 205 | case BasicType.T_OBJECT: { 206 | val = frame.getStack().pop().getObject(); 207 | 208 | break; 209 | } 210 | case BasicType.T_LONG: { 211 | val = frame.getStack().popDouble(); 212 | break; 213 | } 214 | case BasicType.T_DOUBLE: { 215 | val = frame.getStack().popDouble(); 216 | 217 | break; 218 | } 219 | case BasicType.T_ARRAY: { 220 | throw new Error("数组类型, 未作处理"); 221 | } 222 | default: 223 | throw new Error("无法识别的参数类型"); 224 | 225 | } 226 | return val; 227 | 228 | } 229 | 230 | public void pushField(Object o, JavaVFrame frame) { 231 | switch (returnElement.getType()) { 232 | case BasicType.T_CHAR: 233 | frame.getStack().push(new StackValue(BasicType.T_CHAR, (char)o)); 234 | break; 235 | case BasicType.T_INT: 236 | frame.getStack().push(new StackValue(BasicType.T_INT, (int)o)); 237 | break; 238 | case BasicType.T_OBJECT: 239 | frame.getStack().push(new StackValue(BasicType.T_OBJECT, o)); 240 | break; 241 | case BasicType.T_LONG: 242 | frame.getStack().push(new StackValue(BasicType.T_LONG, (int)o)); 243 | break; 244 | case BasicType.T_DOUBLE: 245 | frame.getStack().push(new StackValue(BasicType.T_DOUBLE, (int)o)); 246 | break; 247 | case BasicType.T_ARRAY: 248 | throw new Error("数组类型,未作处理"); 249 | default: 250 | throw new Error("无法识别的参数类型"); 251 | } 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/interpreter/Bytecodes.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.interpreter; 2 | 3 | public class Bytecodes { 4 | 5 | public static final int ILLEGAL = -1; 6 | 7 | public static final int NOP = 0; // 0x00 8 | public static final int ACONST_NULL = 1; // 0x01 9 | public static final int ICONST_M1 = 2; // 0x02 10 | public static final int ICONST_0 = 3; // 0x03 11 | public static final int ICONST_1 = 4; // 0x04 12 | public static final int ICONST_2 = 5; // 0x05 13 | public static final int ICONST_3 = 6; // 0x06 14 | public static final int ICONST_4 = 7; // 0x07 15 | public static final int ICONST_5 = 8; // 0x08 16 | public static final int LCONST_0 = 9; // 0x09 17 | public static final int LCONST_1 = 10; // 0x0a 18 | public static final int FCONST_0 = 11; // 0x0b 19 | public static final int FCONST_1 = 12; // 0x0c 20 | public static final int FCONST_2 = 13; // 0x0d 21 | public static final int DCONST_0 = 14; // 0x0e 22 | public static final int DCONST_1 = 15; // 0x0f 23 | public static final int BIPUSH = 16; // 0x10 24 | public static final int SIPUSH = 17; // 0x11 25 | public static final int LDC = 18; // 0x12 26 | public static final int LDC_W = 19; // 0x13 27 | public static final int LDC2_W = 20; // 0x14 28 | public static final int ILOAD = 21; // 0x15 29 | public static final int LLOAD = 22; // 0x16 30 | public static final int FLOAD = 23; // 0x17 31 | public static final int DLOAD = 24; // 0x18 32 | public static final int ALOAD = 25; // 0x19 33 | public static final int ILOAD_0 = 26; // 0x1a 34 | public static final int ILOAD_1 = 27; // 0x1b 35 | public static final int ILOAD_2 = 28; // 0x1c 36 | public static final int ILOAD_3 = 29; // 0x1d 37 | public static final int LLOAD_0 = 30; // 0x1e 38 | public static final int LLOAD_1 = 31; // 0x1f 39 | public static final int LLOAD_2 = 32; // 0x20 40 | public static final int LLOAD_3 = 33; // 0x21 41 | public static final int FLOAD_0 = 34; // 0x22 42 | public static final int FLOAD_1 = 35; // 0x23 43 | public static final int FLOAD_2 = 36; // 0x24 44 | public static final int FLOAD_3 = 37; // 0x25 45 | public static final int DLOAD_0 = 38; // 0x26 46 | public static final int DLOAD_1 = 39; // 0x27 47 | public static final int DLOAD_2 = 40; // 0x28 48 | public static final int DLOAD_3 = 41; // 0x29 49 | public static final int ALOAD_0 = 42; // 0x2a 50 | public static final int ALOAD_1 = 43; // 0x2b 51 | public static final int ALOAD_2 = 44; // 0x2c 52 | public static final int ALOAD_3 = 45; // 0x2d 53 | public static final int IALOAD = 46; // 0x2e 54 | public static final int LALOAD = 47; // 0x2f 55 | public static final int FALOAD = 48; // 0x30 56 | public static final int DALOAD = 49; // 0x31 57 | public static final int AALOAD = 50; // 0x32 58 | public static final int BALOAD = 51; // 0x33 59 | public static final int CALOAD = 52; // 0x34 60 | public static final int SALOAD = 53; // 0x35 61 | public static final int ISTORE = 54; // 0x36 62 | public static final int LSTORE = 55; // 0x37 63 | public static final int FSTORE = 56; // 0x38 64 | public static final int DSTORE = 57; // 0x39 65 | public static final int ASTORE = 58; // 0x3a 66 | public static final int ISTORE_0 = 59; // 0x3b 67 | public static final int ISTORE_1 = 60; // 0x3c 68 | public static final int ISTORE_2 = 61; // 0x3d 69 | public static final int ISTORE_3 = 62; // 0x3e 70 | public static final int LSTORE_0 = 63; // 0x3f 71 | public static final int LSTORE_1 = 64; // 0x40 72 | public static final int LSTORE_2 = 65; // 0x41 73 | public static final int LSTORE_3 = 66; // 0x42 74 | public static final int FSTORE_0 = 67; // 0x43 75 | public static final int FSTORE_1 = 68; // 0x44 76 | public static final int FSTORE_2 = 69; // 0x45 77 | public static final int FSTORE_3 = 70; // 0x46 78 | public static final int DSTORE_0 = 71; // 0x47 79 | public static final int DSTORE_1 = 72; // 0x48 80 | public static final int DSTORE_2 = 73; // 0x49 81 | public static final int DSTORE_3 = 74; // 0x4a 82 | public static final int ASTORE_0 = 75; // 0x4b 83 | public static final int ASTORE_1 = 76; // 0x4c 84 | public static final int ASTORE_2 = 77; // 0x4d 85 | public static final int ASTORE_3 = 78; // 0x4e 86 | public static final int IASTORE = 79; // 0x4f 87 | public static final int LASTORE = 80; // 0x50 88 | public static final int FASTORE = 81; // 0x51 89 | public static final int DASTORE = 82; // 0x52 90 | public static final int AASTORE = 83; // 0x53 91 | public static final int BASTORE = 84; // 0x54 92 | public static final int CASTORE = 85; // 0x55 93 | public static final int SASTORE = 86; // 0x56 94 | public static final int POP = 87; // 0x57 95 | public static final int POP2 = 88; // 0x58 96 | public static final int DUP = 89; // 0x59 97 | public static final int DUP_X1 = 90; // 0x5a 98 | public static final int DUP_X2 = 91; // 0x5b 99 | public static final int DUP2 = 92; // 0x5c 100 | public static final int DUP2_X1 = 93; // 0x5d 101 | public static final int DUP2_X2 = 94; // 0x5e 102 | public static final int SWAP = 95; // 0x5f 103 | public static final int IADD = 96; // 0x60 104 | public static final int LADD = 97; // 0x61 105 | public static final int FADD = 98; // 0x62 106 | public static final int DADD = 99; // 0x63 107 | public static final int ISUB = 100; // 0x64 108 | public static final int LSUB = 101; // 0x65 109 | public static final int FSUB = 102; // 0x66 110 | public static final int DSUB = 103; // 0x67 111 | public static final int IMUL = 104; // 0x68 112 | public static final int LMUL = 105; // 0x69 113 | public static final int FMUL = 106; // 0x6a 114 | public static final int DMUL = 107; // 0x6b 115 | public static final int IDIV = 108; // 0x6c 116 | public static final int LDIV = 109; // 0x6d 117 | public static final int FDIV = 110; // 0x6e 118 | public static final int DDIV = 111; // 0x6f 119 | public static final int IREM = 112; // 0x70 120 | public static final int LREM = 113; // 0x71 121 | public static final int FREM = 114; // 0x72 122 | public static final int DREM = 115; // 0x73 123 | public static final int INEG = 116; // 0x74 124 | public static final int LNEG = 117; // 0x75 125 | public static final int FNEG = 118; // 0x76 126 | public static final int DNEG = 119; // 0x77 127 | public static final int ISHL = 120; // 0x78 128 | public static final int LSHL = 121; // 0x79 129 | public static final int ISHR = 122; // 0x7a 130 | public static final int LSHR = 123; // 0x7b 131 | public static final int IUSHR = 124; // 0x7c 132 | public static final int LUSHR = 125; // 0x7d 133 | public static final int IAND = 126; // 0x7e 134 | public static final int LAND = 127; // 0x7f 135 | public static final int IOR = 128; // 0x80 136 | public static final int LOR = 129; // 0x81 137 | public static final int IXOR = 130; // 0x82 138 | public static final int LXOR = 131; // 0x83 139 | public static final int IINC = 132; // 0x84 140 | public static final int I2L = 133; // 0x85 141 | public static final int I2F = 134; // 0x86 142 | public static final int I2D = 135; // 0x87 143 | public static final int L2I = 136; // 0x88 144 | public static final int L2F = 137; // 0x89 145 | public static final int L2D = 138; // 0x8a 146 | public static final int F2I = 139; // 0x8b 147 | public static final int F2L = 140; // 0x8c 148 | public static final int F2D = 141; // 0x8d 149 | public static final int D2I = 142; // 0x8e 150 | public static final int D2L = 143; // 0x8f 151 | public static final int D2F = 144; // 0x90 152 | public static final int I2B = 145; // 0x91 153 | public static final int I2C = 146; // 0x92 154 | public static final int I2S = 147; // 0x93 155 | public static final int LCMP = 148; // 0x94 156 | public static final int FCMPL = 149; // 0x95 157 | public static final int FCMPG = 150; // 0x96 158 | public static final int DCMPL = 151; // 0x97 159 | public static final int DCMPG = 152; // 0x98 160 | public static final int IFEQ = 153; // 0x99 161 | public static final int IFNE = 154; // 0x9a 162 | public static final int IFLT = 155; // 0x9b 163 | public static final int IFGE = 156; // 0x9c 164 | public static final int IFGT = 157; // 0x9d 165 | public static final int IFLE = 158; // 0x9e 166 | public static final int IF_ICMPEQ = 159; // 0x9f 167 | public static final int IF_ICMPNE = 160; // 0xa0 168 | public static final int IF_ICMPLT = 161; // 0xa1 169 | public static final int IF_ICMPGE = 162; // 0xa2 170 | public static final int IF_ICMPGT = 163; // 0xa3 171 | public static final int IF_ICMPLE = 164; // 0xa4 172 | public static final int IF_ACMPEQ = 165; // 0xa5 173 | public static final int IF_ACMPNE = 166; // 0xa6 174 | public static final int GOTO = 167; // 0xa7 175 | public static final int JSR = 168; // 0xa8 176 | public static final int RET = 169; // 0xa9 177 | public static final int TABLESWITCH = 170; // 0xaa 178 | public static final int LOOKUPSWITCH = 171; // 0xab 179 | public static final int IRETURN = 172; // 0xac 180 | public static final int LRETURN = 173; // 0xad 181 | public static final int FRETURN = 174; // 0xae 182 | public static final int DRETURN = 175; // 0xaf 183 | public static final int ARETURN = 176; // 0xb0 184 | public static final int RETURN = 177; // 0xb1 185 | public static final int GETSTATIC = 178; // 0xb2 186 | public static final int PUTSTATIC = 179; // 0xb3 187 | public static final int GETFIELD = 180; // 0xb4 188 | public static final int PUTFIELD = 181; // 0xb5 189 | public static final int INVOKEVIRTUAL = 182; // 0xb6 190 | public static final int INVOKESPECIAL = 183; // 0xb7 191 | public static final int INVOKESTATIC = 184; // 0xb8 192 | public static final int INVOKEINTERFACE = 185; // 0xb9 193 | public static final int INVOKEDYNAMIC = 186; // 0xba 194 | public static final int NEW = 187; // 0xbb 195 | public static final int NEWARRAY = 188; // 0xbc 196 | public static final int ANEWARRAY = 189; // 0xbd 197 | public static final int ARRAYLENGTH = 190; // 0xbe 198 | public static final int ATHROW = 191; // 0xbf 199 | public static final int CHECKCAST = 192; // 0xc0 200 | public static final int INSTANCEOF = 193; // 0xc1 201 | public static final int MONITORENTER = 194; // 0xc2 202 | public static final int MONITOREXIT = 195; // 0xc3 203 | public static final int WIDE = 196; // 0xc4 204 | public static final int MULTIANEWARRAY = 197; // 0xc5 205 | public static final int IFNULL = 198; // 0xc6 206 | public static final int IFNONNULL = 199; // 0xc7 207 | public static final int GOTO_W = 200; // 0xc8 208 | public static final int JSR_W = 201; // 0xc9 209 | public static final int BREAKPOINT = 202; // 0xca 210 | 211 | public static final int NUMBER_OF_JAVA_CODES = 203; 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/com/cover/jvm/hotspot/src/share/vm/classfile/ClassFileParser.java: -------------------------------------------------------------------------------- 1 | package com.cover.jvm.hotspot.src.share.vm.classfile; 2 | 3 | import com.cover.jvm.hotspot.src.share.tools.DataTranslate; 4 | import com.cover.jvm.hotspot.src.share.tools.Stream; 5 | import com.cover.jvm.hotspot.src.share.vm.interpreter.BytecodeStream; 6 | import com.cover.jvm.hotspot.src.share.vm.oops.*; 7 | import com.cover.jvm.hotspot.src.share.vm.utilities.AccessFlags; 8 | import com.cover.jvm.jdk.classes.sun.misc.AppClassLoader; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class ClassFileParser { 13 | 14 | private static Logger logger = LoggerFactory.getLogger(ClassFileParser.class); 15 | 16 | public static InstanceKlass parseClassFile(AppClassLoader appClassLoader, byte[] content) { 17 | int index = 0; 18 | InstanceKlass klass = new InstanceKlass(); 19 | byte[] u2Arr = new byte[2]; 20 | byte[] u4Arr = new byte[4]; 21 | 22 | // 魔数 4B 23 | Stream.readU4Simple(content, 0, klass.getMagic()); 24 | index += 4; 25 | 26 | // 次版本号 2B 27 | Stream.readU2Simple(content, index, klass.getMinorVersion()); 28 | index += 2; 29 | 30 | // 主版本号 2B 31 | Stream.readU2Simple(content, index, klass.getMajorVersion()); 32 | index += 2; 33 | 34 | // 常量池大小 2B 35 | Stream.readU2Simple(content, index, u2Arr); 36 | index += 2; 37 | 38 | klass.getConstantPool().setLength(DataTranslate.byteToUnsignedShort(u2Arr)); 39 | klass.getConstantPool().initContainer(); 40 | 41 | // 常量池 N字节 42 | index = parseContentPool(content, klass, index); 43 | 44 | // 类的访问权限 2B 45 | Stream.readU2Simple(content, index, u2Arr); 46 | index += 2; 47 | 48 | klass.setAccessFlag(DataTranslate.byteToUnsignedShort(u2Arr)); 49 | 50 | // 类名 2B 51 | Stream.readU2Simple(content, index, u2Arr); 52 | index += 2; 53 | 54 | klass.setThisClass(DataTranslate.byteToUnsignedShort(u2Arr)); 55 | 56 | // 父类名 2B 57 | Stream.readU2Simple(content, index, u2Arr); 58 | index += 2; 59 | 60 | klass.setSuperClass(DataTranslate.byteToUnsignedShort(u2Arr)); 61 | 62 | // 实现的接口个数 2B 63 | Stream.readU2Simple(content, index, u2Arr); 64 | index += 2; 65 | 66 | klass.setInterfacesLength(DataTranslate.byteToUnsignedShort(u2Arr)); 67 | 68 | // 实现的接口 69 | if (0 != klass.getInterfacesLength()) { 70 | logger.info("开始解析实现的接口信息: "); 71 | index = parseInterface(content, klass, index); 72 | } 73 | // 属性数量 2B 74 | Stream.readU2Simple(content, index, u2Arr); 75 | index += 2; 76 | 77 | klass.setFieldsLength(DataTranslate.byteToUnsignedShort(u2Arr)); 78 | 79 | // 属性 80 | index = parseFields(content, klass, index); 81 | 82 | // 方法数量 2B 83 | Stream.readU2Simple(content, index, u2Arr); 84 | index += 2; 85 | 86 | klass.setMethodLength(DataTranslate.byteToUnsignedShort(u2Arr)); 87 | 88 | klass.initMethodsContainer(); 89 | 90 | // 方法 91 | index = parseMethods(content, klass, index); 92 | 93 | // 属性数量 94 | Stream.readU2Simple(content, index, u2Arr); 95 | index += 2; 96 | 97 | klass.setAttributeLength(DataTranslate.byteToUnsignedShort(u2Arr)); 98 | 99 | logger.info("开始解析类的属性, 数量: " + klass.getAttributeLength()); 100 | 101 | // 属性 102 | for (int i = 0; i < klass.getAttributeLength(); i++) { 103 | Stream.readU2Simple(content, index, u2Arr); 104 | String attrName = (String)klass.getConstantPool().getDataMap().get(DataTranslate.byteToUnsignedShort(u2Arr)); 105 | if (attrName.equals("SourceFile")) { 106 | index = parseSourceFile(content, index, klass, attrName); 107 | } else if (attrName.equals("RuntimeInvisibleAnnotations")) { 108 | index = parseRuntimeInvisibleAnnotations(content, index, klass, attrName); 109 | } else if (attrName.equals("RuntimeVisibleAnnotations")) { 110 | index = parseRuntimeVisibleAnnotations(content, index, klass, attrName); 111 | } else if (attrName.equals("InnerClasses")) { 112 | index = parseInnerClasses(content, index, klass, attrName); 113 | } else if (attrName.equals("BootstrapMethods")) { 114 | index = parseBootstrapMethods(content, index, klass, attrName); 115 | } else { 116 | throw new Error("无法识别的类属性:" + attrName); 117 | } 118 | 119 | } 120 | 121 | return klass; 122 | } 123 | 124 | private static int parseBootstrapMethods(byte[] content, int index, InstanceKlass klass, String attrName) { 125 | byte[] u2Arr = new byte[2]; 126 | byte[] u4Arr = new byte[4]; 127 | 128 | BootstrapMethods bootstrapMethods = new BootstrapMethods(); 129 | klass.getAttributeInfos().put(attrName, bootstrapMethods); 130 | 131 | // name index 132 | Stream.readU2Simple(content, index, u2Arr); 133 | index += 2; 134 | 135 | bootstrapMethods.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 136 | bootstrapMethods.setAttrName((String) klass.getConstantPool().getDataMap().get(bootstrapMethods.getAttrNameIndex())); 137 | 138 | // length 139 | Stream.readU4Simple(content, index, u4Arr); 140 | index += 4; 141 | 142 | 143 | bootstrapMethods.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 144 | 145 | // inner classes num 146 | Stream.readU2Simple(content, index, u2Arr); 147 | index += 2; 148 | 149 | bootstrapMethods.setNumBootstrapMethods(DataTranslate.byteToUnsignedShort(u2Arr)); 150 | 151 | logger.info("\t 第 " + klass.getAttributeInfos().size() + " 个属性: " + 152 | "name: " + bootstrapMethods.getAttrName() 153 | + ", num : " + bootstrapMethods.getNumBootstrapMethods()); 154 | 155 | for (int i = 0; i < bootstrapMethods.getNumBootstrapMethods(); i++) { 156 | BootstrapMethods.Item item = bootstrapMethods.new Item(); 157 | bootstrapMethods.getBootstrapMethods().add(item); 158 | 159 | // bootstrap method ref 160 | Stream.readU2Simple(content, index, u2Arr); 161 | index += 2; 162 | 163 | item.setBootstrapMethodRef(DataTranslate.byteToUnsignedShort(u2Arr)); 164 | 165 | // num bootstrap arguments 166 | Stream.readU2Simple(content, index, u2Arr); 167 | index += 2; 168 | 169 | item.setNumBootstrapArguments(DataTranslate.byteToUnsignedShort(u2Arr)); 170 | item.initContainer(); 171 | 172 | // bootstrap arguments 173 | for (int j = 0; j < item.getNumBootstrapArguments(); j++) { 174 | Stream.readU2Simple(content, index, u2Arr); 175 | index += 2; 176 | 177 | item.getBootstrapArguments()[j] = DataTranslate.byteToUnsignedShort(u2Arr); 178 | } 179 | } 180 | 181 | return index; 182 | } 183 | 184 | private static int parseInnerClasses(byte[] content, int index, InstanceKlass klass, String attrName) { 185 | byte[] u2Arr = new byte[2]; 186 | byte[] u4Arr = new byte[4]; 187 | 188 | InnerClasses innerClasses = new InnerClasses(); 189 | klass.getAttributeInfos().put(attrName, innerClasses); 190 | 191 | // name index 192 | Stream.readU2Simple(content, index, u2Arr); 193 | index += 2; 194 | 195 | innerClasses.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 196 | innerClasses.setAttrName((String) klass.getConstantPool().getDataMap().get(innerClasses.getAttrNameIndex())); 197 | 198 | // length 199 | Stream.readU4Simple(content, index, u4Arr); 200 | index += 4; 201 | 202 | innerClasses.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 203 | 204 | // inner classes num 205 | Stream.readU2Simple(content, index, u2Arr); 206 | index += 2; 207 | 208 | innerClasses.setNumOfClasses(DataTranslate.byteToUnsignedShort(u2Arr)); 209 | 210 | logger.info("\t 第 " + klass.getAttributeInfos().size() + " 个属性: " 211 | + " name: " + innerClasses.getAttrName() 212 | + ", classes num: " + innerClasses.getNumOfClasses()); 213 | for (int i = 0; i < innerClasses.getNumOfClasses(); i++) { 214 | InnerClasses.Item item = innerClasses.new Item(); 215 | 216 | innerClasses.getClasses().add(item); 217 | 218 | // inner class info index 219 | Stream.readU2Simple(content, index, u2Arr); 220 | index += 2; 221 | 222 | item.setInterClassInfoIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 223 | // outer class info index 224 | Stream.readU2Simple(content, index, u2Arr); 225 | index += 2; 226 | 227 | item.setOuterClassInfoIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 228 | 229 | // inner class index 230 | Stream.readU2Simple(content, index, u2Arr); 231 | index += 2; 232 | 233 | item.setInnerNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 234 | 235 | // access flags 236 | Stream.readU2Simple(content, index, u2Arr); 237 | index += 2; 238 | 239 | item.setAccessFlags(new AccessFlags(DataTranslate.byteToUnsignedShort(u2Arr))); 240 | 241 | logger.info("\t\t inter class index: " + item.getInterClassInfoIndex() 242 | + ", outer class index: " + item.getOuterClassInfoIndex() 243 | + ", inner name index: " + item.getInnerNameIndex() 244 | + ", acess flag : " + item.getAccessFlags().getFlag()); 245 | } 246 | 247 | return index; 248 | } 249 | 250 | private static int parseRuntimeVisibleAnnotations(byte[] content, int index, InstanceKlass klass, String attrName) { 251 | byte[] u2Arr = new byte[2]; 252 | byte[] u4Arr = new byte[4]; 253 | 254 | RuntimeVisibleAnnotations attributeInfo = new RuntimeVisibleAnnotations(); 255 | klass.getAttributeInfos().put(attrName, attributeInfo); 256 | 257 | // name index 258 | Stream.readU2Simple(content, index, u2Arr); 259 | index += 2; 260 | 261 | attributeInfo.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 262 | attributeInfo.setAttrName((String) klass.getConstantPool().getDataMap().get(attributeInfo.getAttrNameIndex())); 263 | 264 | // length 265 | Stream.readU4Simple(content, index, u4Arr); 266 | index += 4; 267 | 268 | attributeInfo.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 269 | 270 | // annotation num 271 | Stream.readU2Simple(content, index, u2Arr); 272 | index += 2; 273 | 274 | attributeInfo.setAnnotationsNum(DataTranslate.byteToUnsignedShort(u2Arr)); 275 | 276 | // annotations 277 | for (int i = 0; i < attributeInfo.getAnnotationsNum(); i++) { 278 | Annotation annotation = new Annotation(); 279 | attributeInfo.getAnnotations().add(annotation); 280 | 281 | // type index 282 | Stream.readU2Simple(content, index, u2Arr); 283 | index += 2; 284 | 285 | annotation.setTypeIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 286 | annotation.setTypeStr((String) klass.getConstantPool().getDataMap().get(annotation.getTypeIndex())); 287 | 288 | // elements num 289 | Stream.readU2Simple(content, index, u2Arr); 290 | index += 2; 291 | 292 | annotation.setElementsNum(DataTranslate.byteToUnsignedShort(u2Arr)); 293 | if (0 != annotation.getElementsNum()) { 294 | throw new Error("未做处理"); 295 | } 296 | 297 | logger.info("\t 属性: " + attributeInfo.getAttrName() 298 | + ", name: " + annotation.getTypeStr() 299 | + ", length: " + annotation.getElementsNum()); 300 | } 301 | return index; 302 | } 303 | 304 | private static int parseRuntimeInvisibleAnnotations(byte[] content, int index, InstanceKlass klass, String attrName) { 305 | byte[] u2Arr = new byte[2]; 306 | byte[] u4Arr = new byte[4]; 307 | 308 | RuntimeInvisibleAnnotations attributeInfo = new RuntimeInvisibleAnnotations(); 309 | klass.getAttributeInfos().put(attrName, attributeInfo); 310 | 311 | // name index 312 | Stream.readU2Simple(content, index, u2Arr); 313 | index += 2; 314 | 315 | attributeInfo.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 316 | attributeInfo.setAttrName((String) klass.getConstantPool().getDataMap().get(attributeInfo.getAttrNameIndex())); 317 | 318 | // length 319 | Stream.readU4Simple(content, index, u4Arr); 320 | index += 4; 321 | 322 | attributeInfo.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 323 | 324 | // annotations num 325 | Stream.readU2Simple(content, index, u2Arr); 326 | index += 2; 327 | 328 | // annotations 329 | for (int i = 0; i < attributeInfo.getAnnotationsNum(); i++) { 330 | Annotation annotation = new Annotation(); 331 | attributeInfo.getAnnotations().add(annotation); 332 | 333 | // type index 334 | Stream.readU2Simple(content, index, u2Arr); 335 | index += 2; 336 | 337 | annotation.setTypeIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 338 | annotation.setTypeStr((String) klass.getConstantPool().getDataMap().get(annotation.getTypeIndex())); 339 | 340 | // elements num 341 | Stream.readU2Simple(content, index, u2Arr); 342 | index += 2; 343 | 344 | annotation.setElementsNum(DataTranslate.byteToUnsignedShort(u2Arr)); 345 | if (0 != annotation.getElementsNum()) { 346 | throw new Error("未做处理"); 347 | } 348 | 349 | logger.info("\t 第 " + attributeInfo.getAnnotations().size() + " 个属性:" + attributeInfo.getAttrName() 350 | + " , name: " + annotation.getTypeStr() 351 | + " , length: " + annotation.getElementsNum()); 352 | } 353 | return index; 354 | } 355 | 356 | private static int parseSourceFile(byte[] content, int index, InstanceKlass klass, String attrName) { 357 | byte[] u2Arr = new byte[2]; 358 | byte[] u4Arr = new byte[4]; 359 | 360 | AttributeInfo attributeInfo = new AttributeInfo(); 361 | 362 | klass.getAttributeInfos().put(attrName, attributeInfo); 363 | 364 | // name index 365 | Stream.readU2Simple(content, index, u2Arr); 366 | index += 2; 367 | 368 | attributeInfo.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 369 | 370 | // length 371 | Stream.readU4Simple(content, index, u4Arr); 372 | index += 4; 373 | attributeInfo.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 374 | 375 | attributeInfo.initContainer(); 376 | 377 | // data 378 | Stream.readU2Simple(content, index, attributeInfo.getContainer()); 379 | index += 2; 380 | 381 | logger.info("\t第 " + klass.getAttributeInfos().size() + " 个属性: " + klass.getConstantPool().getDataMap().get(attributeInfo.getAttrNameIndex()) 382 | + ", name index :" + attributeInfo.getAttrNameIndex() 383 | + ", length: " + attributeInfo.getAttrLength() 384 | + ", data: " + DataTranslate.byteToUnsignedShort(attributeInfo.getContainer()) 385 | + ", ( " + klass.getConstantPool().getDataMap().get(DataTranslate.byteToUnsignedShort(attributeInfo.getContainer())) + " )"); 386 | 387 | return index; 388 | } 389 | 390 | private static int parseMethods(byte[] content, InstanceKlass klass, int index) { 391 | for (int i = 0; i < klass.getMethodLength(); i++) { 392 | byte[] u2Arr = new byte[2]; 393 | byte[] u4Arr = new byte[4]; 394 | 395 | MethodInfo methodInfo = new MethodInfo(); 396 | methodInfo.setBelongKlass(klass); 397 | klass.getMethods()[i] = methodInfo; 398 | 399 | // access flag 400 | Stream.readU2Simple(content, index, u2Arr); 401 | index += 2; 402 | 403 | methodInfo.setAccessFlags(new AccessFlags(DataTranslate.byteToUnsignedShort(u2Arr))); 404 | 405 | // name index 406 | Stream.readU2Simple(content, index, u2Arr); 407 | index += 2; 408 | 409 | methodInfo.setNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 410 | methodInfo.setMethodName((String)methodInfo.getBelongKlass().getConstantPool().getDataMap().get(methodInfo.getNameIndex())); 411 | 412 | logger.info("解析方法: " + methodInfo.getMethodName()); 413 | 414 | // descriptor index 415 | Stream.readU2Simple(content, index, u2Arr); 416 | index += 2; 417 | 418 | methodInfo.setDescriptorIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 419 | 420 | // 解析出来参数个数、参数类型、返回值类型 421 | DescriptorStream2 stream = new DescriptorStream2((String) methodInfo.getBelongKlass().getConstantPool().getDataMap().get(methodInfo.getDescriptorIndex())); 422 | stream.parseMethod(); 423 | 424 | methodInfo.setDescriptor(stream); 425 | 426 | // attribute count 427 | Stream.readU2Simple(content, index, u2Arr); 428 | index += 2; 429 | 430 | methodInfo.setAttributesCount(DataTranslate.byteToUnsignedShort(u2Arr)); 431 | 432 | methodInfo.initAttributeContainer(); 433 | 434 | logger.info("\t 第 " + i + " 个方法: access flag: " + methodInfo.getAccessFlags() 435 | + ", name index: " + methodInfo.getNameIndex() 436 | + ", descriptor index: " + methodInfo.getDescriptorIndex() 437 | + ", attribute count: " + methodInfo.getAttributesCount()); 438 | 439 | 440 | // 解析方法属性 441 | if (1 != methodInfo.getAttributesCount()) { 442 | throw new Error("方法的属性不止一个"); 443 | } 444 | 445 | for (int j = 0; j < methodInfo.getAttributesCount(); j++) { 446 | CodeAttributeInfo attributeInfo = new CodeAttributeInfo(); 447 | 448 | methodInfo.getAttributes()[j] = attributeInfo; 449 | 450 | // attr name index 451 | Stream.readU2Simple(content, index, u2Arr); 452 | index += 2; 453 | 454 | attributeInfo.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 455 | 456 | // attr length 457 | Stream.readU4Simple(content, index, u4Arr); 458 | index += 4; 459 | 460 | attributeInfo.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 461 | 462 | // max stack 463 | Stream.readU2Simple(content, index, u2Arr); 464 | index += 2; 465 | 466 | attributeInfo.setMaxStack(DataTranslate.byteToUnsignedShort(u2Arr)); 467 | 468 | // max locals 469 | Stream.readU2Simple(content, index, u2Arr); 470 | index += 2; 471 | 472 | attributeInfo.setMaxLocals(DataTranslate.byteToUnsignedShort(u2Arr)); 473 | 474 | // code length 475 | Stream.readU4Simple(content, index, u4Arr); 476 | index += 4; 477 | 478 | attributeInfo.setCodeLength(DataTranslate.byteArrayToInt(u4Arr)); 479 | 480 | // code 481 | BytecodeStream bytecodeStream = new BytecodeStream(methodInfo, attributeInfo); 482 | attributeInfo.setCode(bytecodeStream); 483 | 484 | Stream.readSimple(content, index, attributeInfo.getCodeLength(), bytecodeStream.getCodes()); 485 | index += attributeInfo.getCodeLength(); 486 | 487 | logger.info("\t\t第 " + j + " 个属性: access flags: " + methodInfo.getAccessFlags() 488 | + ", name index: " + attributeInfo.getAttrNameIndex() 489 | + ", stack: " + attributeInfo.getMaxStack() 490 | + ", locals: " + attributeInfo.getMaxLocals() 491 | + ", code len: " + attributeInfo.getCodeLength()); 492 | 493 | 494 | // exception table length 495 | Stream.readU2Simple(content, index, u2Arr); 496 | index += 2; 497 | 498 | attributeInfo.setExceptionTableLength(DataTranslate.byteToUnsignedShort(u2Arr)); 499 | 500 | // attributes count 501 | Stream.readU2Simple(content, index, u2Arr); 502 | index += 2; 503 | 504 | attributeInfo.setAttributesCount(DataTranslate.byteToUnsignedShort(u2Arr)); 505 | 506 | for (int k = 0; k < attributeInfo.getAttributesCount(); k++) { 507 | // attr name index 508 | Stream.readU2Simple(content, index, u2Arr); 509 | 510 | String attrName = (String)klass.getConstantPool().getDataMap().get(DataTranslate.byteToUnsignedShort(u2Arr)); 511 | 512 | if (attrName.equals("LineNumberTable")) { 513 | index = parseLineNumberTable(content, index, attrName, attributeInfo); 514 | } else if (attrName.equals("LocalVariableTable")) { 515 | index = parseLocalVariableTable(content, index, attrName, attributeInfo); 516 | } else if (attrName.equals("StackMapTable")) { 517 | index = parseStackMapTable(content, index, attrName, attributeInfo); 518 | } 519 | } 520 | } 521 | 522 | // 判断是不是main函数 523 | String methodName = (String)klass.getConstantPool().getDataMap().get(methodInfo.getNameIndex()); 524 | String descriptorName = (String)klass.getConstantPool().getDataMap().get(methodInfo.getDescriptorIndex()); 525 | if (methodName.equals("main") && descriptorName.equals("([Ljava/lang/String;)V")) { 526 | logger.info("定位到main函数所在类"); 527 | 528 | BootClassLoader.setMainKlass(klass); 529 | } 530 | 531 | } 532 | 533 | return index; 534 | 535 | } 536 | 537 | private static int parseStackMapTable(byte[] content, int index, String attrName, CodeAttributeInfo attributeInfo) { 538 | byte[] u2Arr = new byte[2]; 539 | byte[] u4Arr = new byte[4]; 540 | 541 | StackMapTable stackMapTable = new StackMapTable(); 542 | 543 | attributeInfo.getAttributes().put(attrName, stackMapTable); 544 | 545 | // attr name index 546 | Stream.readU2Simple(content, index, u2Arr); 547 | index += 2; 548 | 549 | stackMapTable.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 550 | 551 | // attr len 552 | Stream.readU4Simple(content, index, u4Arr); 553 | index += 4; 554 | 555 | stackMapTable.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 556 | 557 | // 跳过后面的后面 558 | index += stackMapTable.getAttrLength(); 559 | 560 | logger.info("\t\t\t stackMapTable: " 561 | + ", name index: " + stackMapTable.getAttrNameIndex() 562 | + ", attr len: " + stackMapTable.getAttrLength()); 563 | 564 | return index; 565 | } 566 | 567 | private static int parseLocalVariableTable(byte[] content, int index, String attrName, CodeAttributeInfo attributeInfo) { 568 | byte[] u2Arr = new byte[2]; 569 | byte[] u4Arr = new byte[4]; 570 | 571 | LocalVariableTable localVariableTable = new LocalVariableTable(); 572 | 573 | attributeInfo.getAttributes().put(attrName, localVariableTable); 574 | 575 | // attr name index 576 | Stream.readU2Simple(content, index, u2Arr); 577 | index += 2; 578 | 579 | localVariableTable.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 580 | 581 | // attr len 582 | Stream.readU4Simple(content, index, u4Arr); 583 | index += 4; 584 | 585 | localVariableTable.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 586 | 587 | // table length 588 | Stream.readU2Simple(content, index, u2Arr); 589 | index += 2; 590 | 591 | localVariableTable.setTableLength(DataTranslate.byteToUnsignedShort(u2Arr)); 592 | 593 | localVariableTable.initTable(); 594 | 595 | logger.info("\t\t\t localVariableTable: " 596 | + ", name index: " + localVariableTable.getAttrNameIndex() 597 | + ", attr len: " + localVariableTable.getAttrLength() 598 | + ", table len: " + localVariableTable.getTableLength()); 599 | 600 | if (0 == localVariableTable.getTableLength()) { 601 | return index; 602 | } 603 | 604 | // table 605 | for (int i = 0; i < localVariableTable.getTableLength(); i++) { 606 | LocalVariableTable.Item item = localVariableTable.new Item(); 607 | 608 | localVariableTable.getTable()[i] = item; 609 | 610 | // start pc 611 | Stream.readU2Simple(content, index, u2Arr); 612 | index += 2; 613 | 614 | item.setStartPc(DataTranslate.byteToUnsignedShort(u2Arr)); 615 | 616 | // length 617 | Stream.readU2Simple(content, index, u2Arr); 618 | index += 2; 619 | 620 | item.setLength(DataTranslate.byteToUnsignedShort(u2Arr)); 621 | 622 | // name index 623 | Stream.readU2Simple(content, index, u2Arr); 624 | index += 2; 625 | 626 | item.setNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 627 | 628 | // descriptor index 629 | Stream.readU2Simple(content, index, u2Arr); 630 | index += 2; 631 | 632 | item.setDescriptorIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 633 | 634 | // index 635 | Stream.readU2Simple(content, index, u2Arr); 636 | index += 2; 637 | 638 | item.setIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 639 | 640 | logger.info("\t\t\t\t第 " + i + " 个属性: " 641 | + ", start pc :" + item.getStartPc() 642 | + ", length: " + item.getLength() 643 | + ", name index: " + item.getNameIndex() 644 | + ", descriptor index: " + item.getDescriptorIndex() 645 | + ", index: " + item.getIndex()); 646 | } 647 | return index; 648 | } 649 | 650 | private static int parseLineNumberTable(byte[] content, int index, String attrName, CodeAttributeInfo attributeInfo) { 651 | byte[] u2Arr = new byte[2]; 652 | byte[] u4Arr = new byte[4]; 653 | 654 | LineNumberTable lineNumberTable = new LineNumberTable(); 655 | 656 | attributeInfo.getAttributes().put(attrName, lineNumberTable); 657 | 658 | // attr name index 659 | Stream.readU2Simple(content, index, u2Arr); 660 | index += 2; 661 | 662 | lineNumberTable.setAttrNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 663 | 664 | // attr len 665 | Stream.readU4Simple(content, index, u4Arr); 666 | index += 4; 667 | 668 | lineNumberTable.setAttrLength(DataTranslate.byteArrayToInt(u4Arr)); 669 | 670 | // table length 671 | Stream.readU2Simple(content, index, u2Arr); 672 | index += 2; 673 | 674 | lineNumberTable.setTableLength(DataTranslate.byteToUnsignedShort(u2Arr)); 675 | 676 | lineNumberTable.initTable(); 677 | 678 | logger.info("\t\t\t lineNumberTable: " 679 | + ", name index: " + lineNumberTable.getAttrNameIndex() 680 | + ", attr len: " + lineNumberTable.getAttrLength() 681 | + ", table len: " + lineNumberTable.getTableLength()); 682 | 683 | // table 684 | if (0 != lineNumberTable.getTableLength()) { 685 | for (int l = 0; l < lineNumberTable.getTableLength(); l ++) { 686 | LineNumberTable.Item item = lineNumberTable.new Item(); 687 | 688 | lineNumberTable.getTable()[l] = item; 689 | 690 | // start pc 691 | Stream.readU2Simple(content, index, u2Arr); 692 | index += 2; 693 | 694 | item.setStartPc(DataTranslate.byteToUnsignedShort(u2Arr)); 695 | 696 | // line number 697 | Stream.readU2Simple(content, index, u2Arr); 698 | index += 2; 699 | 700 | item.setLineNumber(DataTranslate.byteToUnsignedShort(u2Arr)); 701 | 702 | logger.info("\t\t\t第 " + l+ " 个属性: " 703 | + ", start pc: " + item.getStartPc() 704 | + ", line number: " + item.getLineNumber()); 705 | } 706 | } 707 | 708 | return index; 709 | } 710 | 711 | private static int parseFields(byte[] content, InstanceKlass klass, int index) { 712 | logger.info("解析属性:"); 713 | for (int i = 0; i < klass.getFieldsLength(); i++) { 714 | byte[] u2Arr = new byte[2]; 715 | FieldInfo fieldInfo = new FieldInfo(); 716 | klass.getFields().add(fieldInfo); 717 | 718 | // access flag 719 | Stream.readU2Simple(content, index, u2Arr); 720 | index += 2; 721 | 722 | fieldInfo.setAccessFlags(DataTranslate.byteToUnsignedShort(u2Arr)); 723 | 724 | // name index 725 | Stream.readU2Simple(content, index, u2Arr); 726 | index += 2; 727 | 728 | fieldInfo.setNameIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 729 | 730 | // descriptor index 731 | Stream.readU2Simple(content, index, u2Arr); 732 | index += 2; 733 | 734 | fieldInfo.setDescriptorIndex(DataTranslate.byteToUnsignedShort(u2Arr)); 735 | 736 | // attribute count 737 | Stream.readU2Simple(content, index, u2Arr); 738 | index += 2; 739 | 740 | fieldInfo.setAttributesCount(DataTranslate.byteToUnsignedShort(u2Arr)); 741 | 742 | // attribute 743 | if (0 != fieldInfo.getAttributesCount()) { 744 | throw new Error("属性的attribute count != 0"); 745 | } 746 | 747 | logger.info("\t第 " + " 个属性: access flag: " + fieldInfo.getAccessFlags() 748 | + ", name index: " + fieldInfo.getNameIndex() 749 | + ", descriptor index: " + fieldInfo.getDescriptorIndex() 750 | + ", attribute count: " + fieldInfo.getAttributesCount()); 751 | } 752 | 753 | return index; 754 | } 755 | 756 | private static int parseInterface(byte[] content, InstanceKlass klass, int index) { 757 | byte[] u2Arr = new byte[2]; 758 | for (int i = 0; i < klass.getInterfacesLength(); i++) { 759 | Stream.readU2Simple(content, index, u2Arr); 760 | index += 2; 761 | 762 | int val = DataTranslate.byteToUnsignedShort(u2Arr); 763 | String name = klass.getConstantPool().getClassName(val); 764 | 765 | InterfaceInfo interfaceInfo = new InterfaceInfo(val, name); 766 | klass.getInterfaceInfos().add(interfaceInfo); 767 | 768 | logger.info("\t 第 " + (i + 1) + " 个接口: " + name); 769 | } 770 | return index; 771 | } 772 | 773 | private static int parseContentPool(byte[] content, InstanceKlass klass, int index) { 774 | logger.info("解析常量池:"); 775 | byte[] u2Arr = new byte[2]; 776 | byte[] u4Arr = new byte[4]; 777 | byte[] u8Arr = new byte[8]; 778 | 779 | for (int i = 1; i < klass.getConstantPool().getLength(); i++) { 780 | int tag = Stream.readU1Simple(content, index); 781 | index += 1; 782 | 783 | switch (tag) { 784 | case ConstantPool.JVM_CONSTANT_Utf8: { 785 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Utf8; 786 | 787 | // 字符串长度 788 | Stream.readU2Simple(content, index, u2Arr); 789 | index += 2; 790 | 791 | int len = DataTranslate.byteToUnsignedShort(u2Arr); 792 | // 字符串内容 793 | byte[] str = new byte[len]; 794 | 795 | Stream.readSimple(content, index, len, str); 796 | index += len; 797 | 798 | klass.getConstantPool().getDataMap().put(i, new String(str)); 799 | logger.info("\t 第 " + i + " 个: 类型: utf8, 值: " + klass.getConstantPool().getDataMap().get(i)); 800 | break; 801 | } 802 | case ConstantPool.JVM_CONSTANT_Integer: { 803 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Integer; 804 | throw new Error("程序未做处理"); 805 | } 806 | case ConstantPool.JVM_CONSTANT_Float: { 807 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Float; 808 | Stream.readU4Simple(content, index, u4Arr); 809 | index += 4; 810 | 811 | klass.getConstantPool().getDataMap().put(i, DataTranslate.byteToFloat(u4Arr)); 812 | logger.info("\t第 " + i + " 个: 类型: Float, 值: " + klass.getConstantPool().getDataMap().get(i)); 813 | break; 814 | 815 | } 816 | case ConstantPool.JVM_CONSTANT_Long: { 817 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Long; 818 | Stream.readU8Simple(content, index, u8Arr); 819 | 820 | index += 8; 821 | klass.getConstantPool().getDataMap().put(i, DataTranslate.bytesToLong(u8Arr)); 822 | logger.info("\t第 " + " 个: 类型: Long, 值: " + klass.getConstantPool().getDataMap().get(i)); 823 | 824 | /** 825 | * 因为一个long在常量池中需要两个成员项目来存储 826 | * 所以需要处理 827 | */ 828 | klass.getConstantPool().getTag()[++i] = ConstantPool.JVM_CONSTANT_Long; 829 | klass.getConstantPool().getDataMap().put(i, DataTranslate.bytesToLong(u8Arr)); 830 | logger.info("\t第 " + i + " 个: 类型: Long, 值: " + klass.getConstantPool().getDataMap().get(i)); 831 | break; 832 | } 833 | 834 | case ConstantPool.JVM_CONSTANT_Double: { 835 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Double; 836 | 837 | Stream.readU8Simple(content, index, u8Arr); 838 | index += 8; 839 | 840 | klass.getConstantPool().getDataMap().put(i, DataTranslate.bytesToDouble(u8Arr, false)); 841 | 842 | logger.info("\t第 " + i + " 个: 类型: Double, 值: " + klass.getConstantPool().getDataMap().get(i)); 843 | /** 844 | * 因为一个double在常量池中华需要两个成员项目来存储 845 | * 所以需要处理 846 | */ 847 | klass.getConstantPool().getTag()[++i] = ConstantPool.JVM_CONSTANT_Double; 848 | klass.getConstantPool().getDataMap().put(i, DataTranslate.bytesToDouble(u8Arr, false)); 849 | 850 | logger.info("\t第 " + i + " 个: 类型: Double, 值: " + klass.getConstantPool().getDataMap().get(i)); 851 | break; 852 | } 853 | case ConstantPool.JVM_CONSTANT_Class: { 854 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Class; 855 | Stream.readU2Simple(content, index, u2Arr); 856 | index += 2; 857 | klass.getConstantPool().getDataMap().put(i, DataTranslate.byteToUnsignedShort(u2Arr)); 858 | logger.info("\t第 " + i + " 个: 类型: Class, 值: " + klass.getConstantPool().getDataMap().get(i)); 859 | break; 860 | } 861 | case ConstantPool.JVM_CONSTANT_String: { 862 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_String; 863 | 864 | // Utf8_info 865 | Stream.readU2Simple(content, index, u2Arr); 866 | index += 2; 867 | klass.getConstantPool().getDataMap().put(i, DataTranslate.byteToUnsignedShort(u2Arr)); 868 | logger.info("\t第 " + i + " 个: 类型: String, 值无法获取, 因为字符串的内容还未解析到"); 869 | break; 870 | } 871 | case ConstantPool.JVM_CONSTANT_Fieldref: { 872 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Fieldref; 873 | 874 | // Class_info 875 | Stream.readU2Simple(content, index, u2Arr); 876 | index += 2; 877 | 878 | int classIndex = DataTranslate.byteToUnsignedShort(u2Arr); 879 | 880 | // NameAndType info 881 | Stream.readU2Simple(content, index, u2Arr); 882 | index += 2; 883 | 884 | int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2Arr); 885 | 886 | klass.getConstantPool().getDataMap().put(i, classIndex << 16 | nameAndTypeIndex); 887 | logger.info("\t第 " + i + " 个: 类型: Field, 值: 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 888 | break; 889 | } 890 | case ConstantPool.JVM_CONSTANT_Methodref: { 891 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_Methodref; 892 | 893 | // Class_info 894 | Stream.readU2Simple(content, index, u2Arr); 895 | index += 2; 896 | 897 | int classIndex = DataTranslate.byteToUnsignedShort(u2Arr); 898 | 899 | // NameAndType info 900 | Stream.readU2Simple(content, index, u2Arr); 901 | index += 2; 902 | 903 | int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2Arr); 904 | 905 | // 将classIndex与nameAndTypeIndex拼成一个,前十六位是classIndex,后十六位是nameAndTypeIndex 906 | klass.getConstantPool().getDataMap().put(i, classIndex << 16 | nameAndTypeIndex); 907 | logger.info("\t第 " + i + " 个: 类型: Method, 值: 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 908 | break; 909 | 910 | } 911 | case ConstantPool.JVM_CONSTANT_InterfaceMethodref: { 912 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_InterfaceMethodref; 913 | 914 | // Class_info 915 | Stream.readU2Simple(content, index, u2Arr); 916 | index += 2; 917 | 918 | int classIndex = DataTranslate.byteToUnsignedShort(u2Arr); 919 | 920 | // NameAndType info 921 | Stream.readU2Simple(content, index, u2Arr); 922 | index += 2; 923 | 924 | int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2Arr); 925 | // 将classIndex与nameAndTypeIndex拼成一个,前十六位是classIndex,后十六位是nameAndTypeIndex 926 | klass.getConstantPool().getDataMap().put(i, classIndex << 16 | nameAndTypeIndex); 927 | logger.info("\t第 " + i + " 个: 类型: InterfaceMethodreg, 值: 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 928 | break; 929 | } 930 | case ConstantPool.JVM_CONSTANT_NameAndType: { 931 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_NameAndType; 932 | 933 | // 方法名 934 | Stream.readU2Simple(content, index, u2Arr); 935 | index += 2; 936 | 937 | int methodNameIndex = DataTranslate.byteToUnsignedShort(u2Arr); 938 | 939 | // 方法描述符 940 | Stream.readU2Simple(content, index, u2Arr); 941 | index += 2; 942 | 943 | int methodDescriptorIndex = DataTranslate.byteToUnsignedShort(u2Arr); 944 | 945 | klass.getConstantPool().getDataMap().put(i, methodNameIndex << 16 | methodDescriptorIndex); 946 | 947 | logger.info("\t第 " + i + " 个: 类型: NameAndType, 值: 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 948 | break; 949 | } 950 | case ConstantPool.JVM_CONSTANT_MethodHandle: { 951 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_InvokeDynamic; 952 | 953 | // reference kind 954 | byte referenceKind = Stream.readU1Simple(content, index); 955 | index += 1; 956 | 957 | // reference index 958 | Stream.readU2Simple(content, index, u2Arr); 959 | index += 2; 960 | int referenceIndex = DataTranslate.byteToUnsignedShort(u2Arr); 961 | 962 | klass.getConstantPool().getDataMap().put(i, referenceKind << 16 | referenceIndex); 963 | logger.info("\t第 " + i + " 个: 类型: MethodHandle, 值: 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 964 | break; 965 | } 966 | case ConstantPool.JVM_CONSTANT_MethodType: { 967 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_String; 968 | 969 | // descriptor index 970 | Stream.readU2Simple(content, index, u2Arr); 971 | index += 2; 972 | 973 | klass.getConstantPool().getDataMap().put(i, DataTranslate.byteToUnsignedShort(u2Arr)); 974 | 975 | logger.info("\t第 " + i + " 个 : 类型: MethodType, 值: " + klass.getConstantPool().getDataMap().get(i)); 976 | break; 977 | 978 | } 979 | case ConstantPool.JVM_CONSTANT_InvokeDynamic: { 980 | klass.getConstantPool().getTag()[i] = ConstantPool.JVM_CONSTANT_InvokeDynamic; 981 | 982 | // bootstrap method attr 983 | Stream.readU2Simple(content, index, u2Arr); 984 | index += 2; 985 | 986 | int bootstrapMethodAttrIndex = DataTranslate.byteToUnsignedShort(u2Arr); 987 | 988 | // 方法描述符 989 | Stream.readU2Simple(content, index, u2Arr); 990 | index += 2; 991 | 992 | int methodDescriptorIndex = DataTranslate.byteToUnsignedShort(u2Arr); 993 | klass.getConstantPool().getDataMap().put(i, bootstrapMethodAttrIndex << 16 | methodDescriptorIndex); 994 | 995 | logger.info("\t第 " + i + " 个: 类型: InvokeDynamic, 值 : 0x" + Integer.toHexString((int) klass.getConstantPool().getDataMap().get(i))); 996 | 997 | break; 998 | } 999 | default: 1000 | throw new Error("无法识别的常量池项"); 1001 | } 1002 | } 1003 | return index; 1004 | 1005 | } 1006 | } 1007 | --------------------------------------------------------------------------------