diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinarySearchTree.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinarySearchTree.java index 88922462a7..300d302d56 100644 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinarySearchTree.java +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinarySearchTree.java @@ -1,5 +1,10 @@ package me.lzb.basic.tree; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + /** * @author LZB */ @@ -180,30 +185,156 @@ private BinaryTreeNode getFatherNode(BinaryTreeNode node, T t) { if (node.getRight() != null && node.getRight().getData().equals(t)) { return node; } - if (t.compareTo(node.getData()) > 0) { + if (node.isSmallerThanParam(t)) { return getFatherNode(node.getRight(), t); } else { return getFatherNode(node.getLeft(), t); } } - private BinaryTreeNode getNode(BinaryTreeNode node, T t) { + + /** + * 按层次遍历: levelVisit + * + * @return + */ + public List levelVisit() { + List result = new ArrayList<>(); + levelVisit(result, root); + return result; + } + + + private void levelVisit(List list, BinaryTreeNode node) { if (node == null) { - return node; + return; + } + //先放入根节点 + Queue> queue = new LinkedList<>(); + queue.add(node); + while (!queue.isEmpty()) { + //上一层的节点个数 + int l = queue.size(); + //循环取出上一层这些节点 + for (int i = 0; i < l; i++) { + BinaryTreeNode temp = queue.poll(); + list.add(temp.getData()); + //把下一层的节点放入队列 + if (temp.getLeft() != null) { + queue.add(temp.getLeft()); + } + if (temp.getRight() != null) { + queue.add(temp.getRight()); + } + } } + } - if (node.getData().equals(t)) { - return node; + /** + * 判断一个二叉树是不是二叉查找树 + * + * @return + */ + public boolean isValid() { + return isValid(true, root); + } + + private boolean isValid(boolean b, BinaryTreeNode node) { + if (!b || node == null) { + return b; + } + + if (node.getLeft() == null && node.getRight() == null) { + return b; + } + + if (node.getLeft() != null) { + if (node.isSmallerThanParam(node.getLeft())) { + b = false; + } } - if (t.compareTo(node.getData()) > 0) { - return getNode(node.getRight(), t); + if (node.getRight() != null) { + if (node.isBiggerThanParam(node.getRight())) { + b = false; + } + } + + boolean bl = isValid(b, node.getLeft()); + boolean br = isValid(b, node.getRight()); + + return bl && br; + } + + + /** + * 获取两个节点的最小公共祖先 + * + * @param n1 + * @param n2 + * @return + */ + public T getLowestCommonAncestor(T n1, T n2) { + return getLowestCommonAncestor(root, n1, n2); + } + + + private T getLowestCommonAncestor(BinaryTreeNode node, T n1, T n2) { + if (node == null) { + return null; + } + + //找到一个位于两者之间的节点,就是公共祖先。 + if ((node.isSmallerThanParam(n1) && node.isBiggerThanParam(n2)) || (node.isSmallerThanParam(n2) && node.isBiggerThanParam(n1))) { + return node.getData(); + } + + //当前节点比n1和n2都小,最小公共祖先在右子树。 + if (node.isSmallerThanParam(n1) && node.isSmallerThanParam(n2)) { + return getLowestCommonAncestor(node.getRight(), n1, n2); + } + + //当前节点比n1和n2都大,最小公共祖先在左子树。 + if (node.isBiggerThanParam(n1) && node.isBiggerThanParam(n2)) { + return getLowestCommonAncestor(node.getLeft(), n1, n2); + } + return null; + } + + + /** + * 给定两个值, 获得处于这两个值中间的节点 + * + * @param n1 + * @param n2 + * @return + */ + public List getNodesBetween(T n1, T n2) { + List result = new ArrayList<>(); + T s, b; + if (n1.compareTo(n2) < 0) { + s = n1; + b = n2; } else { - return getNode(node.getLeft(), t); + s = n2; + b = n1; } + getNodesBetween(result, root, s, b); + return result; } + private void getNodesBetween(List list, BinaryTreeNode node, T small, T bigger) { + if (node == null) { + return; + } + if (node.isBiggerThanParam(small) && node.isSmallerThanParam(bigger)) { + list.add(node.getData()); + } + + getNodesBetween(list, node.getLeft(), small, bigger); + getNodesBetween(list, node.getRight(), small, bigger); + } } diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java index add0443e9a..597e5a554e 100644 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java @@ -45,7 +45,7 @@ public void setRight(BinaryTreeNode right) { */ public void insert(T d) { BinaryTreeNode b = new BinaryTreeNode(d); - if (isSmaller(d)) { + if (isBiggerThanParam(d)) { //比父节点小,左边 if (this.left == null) { this.left = b; @@ -70,10 +70,22 @@ public void insert(T d) { * @param d data * @return true false */ - private boolean isSmaller(T d) { + public boolean isBiggerThanParam(T d) { return this.data.compareTo(d) > 0; } + public boolean isBiggerThanParam(BinaryTreeNode node) { + return isBiggerThanParam(node.getData()); + } + + public boolean isSmallerThanParam(T d) { + return this.data.compareTo(d) < 0; + } + + public boolean isSmallerThanParam(BinaryTreeNode node) { + return isSmallerThanParam(node.getData()); + } + @Override public String toString() { // return getLeft() != null ? getLeft().getData().toString() : "" + ":" + getData().toString() + ":" + getRight() != null ? getRight().getData().toString() : ""; diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinarySearchTreeTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinarySearchTreeTest.java index 0744eecd67..ef33320d00 100644 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinarySearchTreeTest.java +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinarySearchTreeTest.java @@ -63,4 +63,37 @@ public void testRemoveMiddleNode() { Assert.assertEquals(3, root.getLeft().getData().intValue()); Assert.assertEquals(4, root.getLeft().getRight().getData().intValue()); } + + @Test + public void testLevelVisit() { + Assert.assertEquals("[6, 2, 8, 1, 4, 3]", tree.levelVisit().toString()); + } + + @Test + public void testIsValid() { + Assert.assertTrue(tree.isValid()); + tree.getRoot().getRight().setData(5); + Assert.assertFalse(tree.isValid()); + tree.getRoot().getRight().setData(8); + tree.getRoot().getLeft().getLeft().setData(5); + Assert.assertFalse(tree.isValid()); + } + + @Test + public void testGetLowestCommonAncestor() { + Assert.assertEquals(2l, tree.getLowestCommonAncestor(1, 4).longValue()); + Assert.assertEquals(6l, tree.getLowestCommonAncestor(1, 8).longValue()); + } + + + @Test + public void testGetNodesBetween() { + Assert.assertEquals("[6, 2, 4, 3]", tree.getNodesBetween(1, 8).toString()); + + Assert.assertEquals("[6]", tree.getNodesBetween(7, 4).toString()); + + Assert.assertEquals("[6, 2, 1, 4, 3, 8]", tree.getNodesBetween(20, 0).toString()); + } + + } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java index a1ec8604fb..3a7241eb56 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java @@ -135,6 +135,7 @@ public void addMethod(Method m) { this.methods.add(m); } + //函数的 方法名+参数类型+返回值,构成函数的唯一标识 public Method getMethod(String methodName, String paramAndReturnType) { for (Method m : methods) { int nameIndex = m.getNameIndex(); diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java index 983c8006ff..42f06377c9 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java @@ -4,6 +4,7 @@ import me.lzb.jvm.method.Method; /** + * 定义了返回结果,有时候执行结束了是返回,或者,执行下一个方法,等等 * @author LZB */ public class ExecutionResult { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java index 1ccd6b90b9..b8bf5be24c 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java @@ -12,24 +12,34 @@ */ public class ExecutorEngine { + //虚拟机栈,用一个stack表示 private Stack stack = new Stack<>(); public ExecutorEngine() { } + //开始执行的时候,传入main方法 public void execute(Method mainMethod) { + //执行一个函数,就要new一个函数栈帧 StackFrame stackFrame = StackFrame.create(mainMethod); + //把栈帧放入虚拟机栈 stack.push(stackFrame); + //当statck不为空时,开始循环执行 while (!stack.isEmpty()) { + //取出顶部栈帧 StackFrame frame = stack.peek(); + //执行栈帧 ExecutionResult result = frame.execute(); + //如果执行结果是,暂停当前栈帧,执行一个新的函数,就new一个新栈帧,(函数调用别的函数的情况) if (result.isPauseAndRunNewFrame()) { Method nextMethod = result.getNextMethod(); StackFrame nextFrame = StackFrame.create(nextMethod); + //设置调用他的函数栈帧 nextFrame.setCallerFrame(frame); + //设置传过去的参数,第一个参数都是this setupFunctionCallParams(frame, nextFrame); stack.push(nextFrame); } else { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java index b8cc8b7ffb..76031559af 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java @@ -6,7 +6,7 @@ * @author LZB */ public class Heap { - + //堆,存放new出来的对象 private static Heap instance = new Heap(); private Heap() { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java index 61b2285953..51234026dd 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java @@ -4,6 +4,7 @@ import java.util.Map; /** + * 自己定义一个Object代替java的Object * @author LZB */ public class JavaObject { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java index 562809de3c..9bac56f0b6 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java @@ -17,11 +17,13 @@ public class MethodArea { public static final MethodArea instance = new MethodArea(); /** - * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + * 这里ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型,类装载器有命名空间,和被装载的类是关联的 */ - private ClassFileLoader clzLoader = null; + /** + * 保存load过的class,key:me/lzb/jvm/HourlyEmployee, value:ClassFile对象 + */ Map map = new HashMap<>(); private MethodArea() { @@ -58,24 +60,6 @@ public ClassFile findClassFile(String className) { } - public Method getMethod(String className, String methodName, String paramAndReturnType) { - - ClassFile clz = this.findClassFile(className); - - Method m = clz.getMethod(methodName, paramAndReturnType); - - if (m == null) { - - throw new RuntimeException("method can't be found : \n" - + "class: " + className - + "method: " + methodName - + "paramAndReturnType: " + paramAndReturnType); - } - - return m; - } - - public Method getMethod(MethodRefInfo methodRef) { ClassFile clz = this.findClassFile(methodRef.getClassName()); diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java index 2e76d70d66..6ee8f92d23 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java @@ -16,12 +16,13 @@ public void run(String[] classPaths, String className) throws IOException { loader.addClassPath(classPaths[i]); } + //方法区,存放class文件,常量池 MethodArea methodArea = MethodArea.getInstance(); methodArea.setClassFileLoader(loader); ExecutorEngine engine = new ExecutorEngine(); - + //获取构造函数名 className = className.replace(".", "/"); engine.execute(methodArea.getMainMethod(className)); diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java index 8b266c5981..936341e209 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java @@ -17,6 +17,9 @@ public class StackFrame { private List localVariableTable = new ArrayList<>(); private Stack oprandStack = new Stack<>(); + /** + * 用来记录当前栈帧帧,已经执行到哪一步,以便恢复的时候,继续执行 + */ int index = 0; private Method m = null; @@ -65,8 +68,12 @@ public int getNextCommandIndex(int offset) { throw new RuntimeException("Can't find next command"); } + /** + * 执行栈帧 + * @return + */ public ExecutionResult execute() { - + //取出所有jvm指令 ByteCodeCommand[] commands = m.getCmds(); @@ -76,22 +83,23 @@ public ExecutionResult execute() { //缺省值是执行下一条命令 result.setNextAction(ExecutionResult.RUN_NEXT_CMD); - //输出执行的命令 + //在控制台打印,执行的命令,这里用了visitor设计模式 ExecutionVisitor format = ExecutionFormat.getInstance(); commands[index].printExecute(format); -// System.out.println(commands[index].toString()); - + //执行指令,这里是一个多态,具体执行的内容在各个指令的内部 commands[index].execute(this, result); - if (result.isRunNextCmd()) { + + if (result.isRunNextCmd()) { //当前指令结果是执行下一条指令,就++,继续循环 index++; - } else if (result.isExitCurrentFrame()) { + } else if (result.isExitCurrentFrame()) { //退出当前栈帧,就是return return result; - } else if (result.isPauseAndRunNewFrame()) { + } else if (result.isPauseAndRunNewFrame()) { //暂停当前栈帧的执行,创建新的栈帧 index++; return result; - } else if (result.isJump()) { + + } else if (result.isJump()) { //跳转,要注意偏移量 int offset = result.getNextCmdOffset(); this.index = getNextCommandIndex(offset); } else { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java index a7396bb7d4..87add57f61 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java @@ -31,24 +31,31 @@ public ClassFileParser(byte[] data) { public ClassFile parse() { ClassFile classFile = new ClassFile(); + //class文件的开头四个字节一定是“cafebabe”,叫做magic number parserMagicNumber(classFile); if (!StringUtils.equals(classFile.getMagicNumber(), ConstantInfo.MAGIC_NUMBER)) { throw new RuntimeException("It is not a java class file."); } - + //两个字节的小版本号,两个字节的主版本号 parserVersion(classFile); + //常量池,进去看 parserConstantPool(classFile); + //两个字节的类的访问权限 parserAccessFlag(classFile); + //本class和父类的常量池索引 parserClassIndex(classFile); + //接口部分没有实现 parserInterface(classFile); + //成员变量 parserField(classFile); + //函数 parserMethod(classFile); return classFile; @@ -82,16 +89,37 @@ private void parserVersion(ClassFile classFile) { } private void parserConstantPool(ClassFile classFile) { + //开头两个字节,常量池常量总个数,包括这两个字节(这两字节算一个常量) int count = nextBytesToInt(2); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); - for (int i = 1; i < count; i++) { + //i=1开始,遍历剩下的常量 + for (int i = 1; i < count; i++) { + //每次循环,第一个字节,根据jvm规范,确定常量类型, + //CONSTANT_Class 7 + //CONSTANT_Fieldref 9 + //CONSTANT_Methodref 10 + //CONSTANT_InterfaceMethodref 11 + //CONSTANT_String 8 + //CONSTANT_Integer 3 + //CONSTANT_Float 4 + //CONSTANT_Long 5 + //CONSTANT_Double 6 + //CONSTANT_NameAndType 12 + //CONSTANT_Utf8 1 + //CONSTANT_MethodHandle 15 + //CONSTANT_MethodType 16 + //CONSTANT_InvokeDynamic 18 int tag = nextBytesToInt(1); if (tag == ConstantInfo.Class_info) { + //CONSTANT_Class_info { + // u1 tag; //07 + // u2 name_index; //是一个UTF8类型的常量池的索引 + // } ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(nextBytesToInt(2)); @@ -100,6 +128,12 @@ private void parserConstantPool(ClassFile classFile) { } if (tag == ConstantInfo.Fieldref_info) { + + //CONSTANT_Fieldref_info { + // u1 tag; // 9 + // u2 class_index; //CONSTANT_Class类型的索引,表示这个成员变量是这个类,或者接口的 + // u2 name_and_type_index; //CONSTANT_NameAndType_info类型的索引,表示字段的名字和描述符 + // } FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(nextBytesToInt(2)); fieldRefInfo.setNameAndTypeIndex(nextBytesToInt(2)); @@ -109,6 +143,11 @@ private void parserConstantPool(ClassFile classFile) { } if (tag == ConstantInfo.Methodref_info) { + //CONSTANT_Methodref_info { + // u1 tag; //10 + // u2 class_index; //CONSTANT_Class类型的索引,表示这个成员变量是这个类的(不能是接口) + // u2 name_and_type_index; //CONSTANT_NameAndType_info类型的索引, 方法名&(参数)返回值 println&(Ljava/lang/String;I)V ,类型参数有;结尾L开头,基础数据类型没有;和L + // } MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(nextBytesToInt(2)); methodRefInfo.setNameAndTypeIndex(nextBytesToInt(2)); @@ -118,6 +157,12 @@ private void parserConstantPool(ClassFile classFile) { } if (tag == ConstantInfo.NameAndType_info) { + + //CONSTANT_NameAndType_info { + // u1 tag; //12 + // u2 name_index; //utf8类型索引,方法名或者字段名 + // u2 descriptor_index; //utf8类型索引,字段类型,或者方法的(参数)返回值 + // } NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(nextBytesToInt(2)); nameAndTypeInfo.setIndex2(nextBytesToInt(2)); @@ -127,6 +172,10 @@ private void parserConstantPool(ClassFile classFile) { } if (tag == ConstantInfo.String_info) { + //CONSTANT_String_info { + // u1 tag; //8 + // u2 string_index; //utf8类型常量池索引 + //} StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(nextBytesToInt(2)); @@ -135,6 +184,11 @@ private void parserConstantPool(ClassFile classFile) { } if (tag == ConstantInfo.Utf8_info) { + //CONSTANT_Utf8_info { + // u1 tag; //1 + // u2 length; //bytes[]数组的长度 + // u1 bytes[length]; //字符串常量采用改进过的UTF-8编码表示 + // } UTF8Info utf8Info = new UTF8Info(pool); int len = nextBytesToInt(2); byte[] data = nextBytes(len); @@ -168,8 +222,9 @@ private void parserAccessFlag(ClassFile classFile) { private void parserClassIndex(ClassFile classFile) { ClassIndex clzIndex = new ClassIndex(); - + //本class 常量池class类型索引 int thisClassIndex = nextBytesToInt(2); + //父类 常量池class类型索引 int superClassIndex = nextBytesToInt(2); clzIndex.setThisClassIndex(thisClassIndex); clzIndex.setSuperClassIndex(superClassIndex); @@ -184,40 +239,57 @@ private void parserInterface(ClassFile classFile) { private void parserField(ClassFile classFile) { + //成员变量个数 int count = nextBytesToInt(2); for (int i = 1; i <= count; i++) { - + //访问权限 int accessFlags = nextBytesToInt(2); + //常量池UTF8类型索引,变量名 int nameIndex = nextBytesToInt(2); + //常量池utf8类型索引,变量类型 int descriptorIndex = nextBytesToInt(2); + //当前字段附加属性的个数 int attributesCount = nextBytesToInt(2); - Field f = new Field(accessFlags, nameIndex, descriptorIndex, classFile.getConstantPool()); + Field field = new Field(accessFlags, nameIndex, descriptorIndex, classFile.getConstantPool()); for (int j = 1; j <= attributesCount; j++) { + //属性类型,utf8类型的索引 int attrNameIndex = nextBytesToInt(2); + //获取类型值 String attrName = classFile.getConstantPool().getUTF8String(attrNameIndex); if (AttributeInfo.CONST_VALUE.equals(attrName)) { + //ConstantValue_attribute { + // u2 attribute_name_index; //就是if前面的两个字节,utf8类型索引,表面名字 + // u4 attribute_length; //ConstantValue的attribute_length固定值为2 + // u2 constantvalue_index; // 常量池索引,可以引用基础数据类型和String + // } int attrLen = nextBytesToInt(4); ConstantValue constValue = new ConstantValue(attrNameIndex, attrLen); constValue.setConstValueIndex(nextBytesToInt(2)); - f.setConstantValue(constValue); + field.setConstantValue(constValue); } else { throw new RuntimeException("the attribute " + attrName + " has not been implemented yet."); } } - classFile.addField(f); + classFile.addField(field); } } private void parserMethod(ClassFile classFile) { + //函数个数 int count = nextBytesToInt(2); + for (int i = 1; i <= count; i++) { + //函数访问权限 int accessFlags = nextBytesToInt(2); + //常量池utf8类型索引,函数名 int nameIndex = nextBytesToInt(2); + //常量池utf8类型索引,参数和返回值()V int descriptorIndex = nextBytesToInt(2); + //附加属性数量 int attributesCount = nextBytesToInt(2); @@ -226,11 +298,13 @@ private void parserMethod(ClassFile classFile) { for (int j = 1; j <= attributesCount; j++) { + //附加属性名索引,utf8类型常量池索引 int attributeNameIndex = nextBytesToInt(2); - + //获取属性名 String attributeName = classFile.getConstantPool().getUTF8String(attributeNameIndex); if (StringUtils.equalsIgnoreCase(attributeName, AttributeInfo.CODE)) { + //处理code类型附加属性 parserCodeAttr(attributeNameIndex, method, classFile); continue; } @@ -246,6 +320,25 @@ private void parserMethod(ClassFile classFile) { private void parserCodeAttr(int attributeNameIndex, Method method, ClassFile classFile) { + //Code_attribute { + // u2 attribute_name_index; + // u4 attribute_length; //项的值表示当前属性的长度,不包括开始的6个字节。 + // u2 max_stack; //栈的最大深度 + // u2 max_locals; //分配在当前方法引用的局部变量表中的局部变量个数,包括调用此方法时用于传递参数的局部变量。 + // u4 code_length; //code[]数组的字节数长度(真正要执行的指令都在这里面) + // u1 code[code_length]; //方法的指令集 + // u2 exception_table_length; { + // u2 start_pc; + // u2 end_pc; + // u2 handler_pc; + // u2 catch_type; + // } + // exception_table[exception_table_length]; + // u2 attributes_count; + // attribute_info attributes[attributes_count]; + // } + + // int attributeLength = nextBytesToInt(4); int maxStack = nextBytesToInt(2); int maxLocals = nextBytesToInt(2); @@ -253,7 +346,7 @@ private void parserCodeAttr(int attributeNameIndex, Method method, ClassFile cla String code = nextBytesToString(codeLength); - //处理cmd + //处理cmd,解析需要执行的各种指令 CommandParser commandParser = new CommandParser(code); CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, commandParser.parse(classFile)); diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java index 3e7976a484..e91d70bb06 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java @@ -59,6 +59,9 @@ public ByteCodeCommand[] parse(ClassFile clzFile) { List cmds = new ArrayList<>(); + //这里用到的指令分为3种,没有操作数的(2个字节),一个操作数(4个字节),两个操作数(6个字节) + + while (hasNext()) { String opCode = next2CharAsString();