From 4f3cecbd63b2fa0ee5a8f3d9e10c6b7163f840c5 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Tue, 18 Apr 2017 06:13:33 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=B8=8Eattr=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExprTest.java | 4 + .../coderising/jvm/clz/ClassFile.java | 26 +++-- .../coderising/jvm/field/Field.java | 50 ++++++++++ .../coderising/jvm/method/Method.java | 96 +++++++++++++++++++ .../jvm/test/ClassFileloaderTest.java | 77 ++++++++++++++- 5 files changed, 245 insertions(+), 8 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java index 706aaea86e..a14953535d 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java @@ -46,6 +46,10 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } + { + InfixExpr expr = new InfixExpr("10-30+50-20/10/2*4"); + Assert.assertEquals(26, expr.evaluate(), 0.001f); + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java index c4d13704f2..82eee82fb5 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java @@ -1,9 +1,14 @@ package com.github.miniyk2012.coding2017.coderising.jvm.clz; +import assignments.jvm.field.Field; +import assignments.jvm.method.Method; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ClassInfo; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import java.util.ArrayList; +import java.util.List; + public class ClassFile { private int minorVersion; @@ -12,7 +17,8 @@ public class ClassFile { private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; - + private List fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -24,8 +30,6 @@ public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - public ConstantPool getConstantPool() { return pool; } @@ -43,20 +47,28 @@ public void setMajorVersion(int majorVersion) { } public void setConstPool(ConstantPool pool) { this.pool = pool; - + } + public void addField(Field f){ + this.fields.add(f); + } + public List getFields(){ + return this.fields; + } + public void addMethod(Method m){ + this.methods.add(m); + } + public List getMethods() { + return methods; } public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - public void print(){ - if(this.accessFlag.isPublicClass()){ System.out.println("Access flag : public "); } System.out.println("Class Name:"+ getClassName()); - System.out.println("Super Class Name:"+ getSuperClassName()); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..017e6cd8bc --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.field; + +import assignments.jvm.constant.ConstantPool; +import assignments.jvm.constant.UTF8Info; +import assignments.jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + + private ConstantPool pool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..f9e62fbb93 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java @@ -0,0 +1,96 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.method; + +import assignments.jvm.clz.ClassFile; +import assignments.jvm.attr.AttributeInfo; +import assignments.jvm.attr.CodeAttr; +import assignments.jvm.constant.ConstantPool; +import assignments.jvm.constant.UTF8Info; +import assignments.jvm.loader.ByteCodeIterator; + + + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + + + +public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for( int j=1; j<= attribCount; j++){ + + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else{ + throw new RuntimeException("only CODE attribute is implemented , please implement the "+ attrName); + } + + } + + return m ; + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java index 013ec8073a..21d5ddbd71 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java @@ -1,15 +1,19 @@ package com.github.miniyk2012.coding2017.coderising.jvm.test; +import assignments.jvm.field.Field; +import assignments.jvm.method.Method; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex; import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ClassFileLoader; import com.github.miniyk2012.coding2017.coderising.jvm.util.Util; import org.junit.After; -import org.junit.Assert; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.List; + public class ClassFileloaderTest { @@ -172,5 +176,76 @@ public void testClassIndex(){ Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } + /** + * 下面是第三次JVM课应实现的测试用例 + */ + @Test + public void testReadFields(){ + + List fields = clzFile.getFields(); + Assert.assertEquals(2, fields.size()); + { + Field f = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ + String methodName = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + String code = m.getCodeAttr().getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } } From 51a57fbbc581b82d0ed5ae5a1e7f83bf6fbff9a7 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Tue, 18 Apr 2017 06:58:12 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E5=B0=86=E8=80=81=E5=A4=A7=E7=9A=84Field?= =?UTF-8?q?=E5=92=8CMethod=E6=95=B4=E5=90=88=E5=88=B0=E6=88=91=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/attr/AttributeInfo.java | 19 +++ .../coderising/jvm/attr/CodeAttr.java | 120 ++++++++++++++++++ .../coderising/jvm/attr/LineNumberTable.java | 68 ++++++++++ .../jvm/attr/LocalVariableItem.java | 39 ++++++ .../jvm/attr/LocalVariableTable.java | 57 +++++++++ .../coderising/jvm/attr/StackMapTable.java | 30 +++++ .../coderising/jvm/clz/ClassFile.java | 5 +- .../coderising/jvm/field/Field.java | 14 +- .../jvm/loader/ByteCodeIterator.java | 22 ++++ .../jvm/loader/ClassFileParser.java | 44 ++++++- .../coderising/jvm/method/Method.java | 25 ++-- .../jvm/test/ClassFileloaderTest.java | 4 +- 12 files changed, 422 insertions(+), 25 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/StackMapTable.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..661e65bb2b --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCEPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVariableTable"; + public static final String STACK_MAP_TABLE = "StackMapTable"; + int attrNameIndex; + int attrLen ; + public AttributeInfo(int attrNameIndex, int attrLen) { + + this.attrNameIndex = attrNameIndex; + this.attrLen = attrLen; + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e6b7da9bb6 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,120 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + public String getCode() { + return code; + } + + //private ByteCodeCommand[] cmds ; + //public ByteCodeCommand[] getCmds() { + // return cmds; + //} + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code /*ByteCodeCommand[] cmds*/) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + //this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + +public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + + int attrNameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU4toInt(); + int maxStack = iter.nextU2toInt(); + int maxLocals = iter.nextU2toInt(); + int codeLen = iter.nextU4toInt(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + //ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code); + + int exceptionTableLen = iter.nextU2toInt(); + //TODO 处理exception + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.nextU2toInt(); + + for(int x=1; x<=subAttrCount; x++){ + int subAttrIndex = iter.nextU2toInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.skip(-2); + //line item table + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } + else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } + else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } + else{ + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Code:").append(code).append("\n"); + /*for(int i=0;i items = new ArrayList(); + + private static class LineNumberItem{ + int startPC; + int lineNum; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLineNum() { + return lineNum; + } + public void setLineNum(int lineNum) { + this.lineNum = lineNum; + } + } + public void addLineNumberItem(LineNumberItem item){ + this.items.add(item); + } + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + public static LineNumberTable parse(ByteCodeIterator iter){ + + int index = iter.nextU2toInt(); + int len = iter.nextU4toInt(); + + LineNumberTable table = new LineNumberTable(index,len); + + int itemLen = iter.nextU2toInt(); + + for(int i=1; i<=itemLen; i++){ + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.nextU2toInt()); + item.setLineNum(iter.nextU2toInt()); + table.addLineNumberItem(item); + } + return table; + } + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Line Number Table:\n"); + for(LineNumberItem item : items){ + buffer.append("startPC:"+item.getStartPC()).append(","); + buffer.append("lineNum:"+item.getLineNum()).append("\n"); + } + buffer.append("\n"); + return buffer.toString(); + + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableItem.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..8d2c4da5c7 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + +public class LocalVariableItem { + private int startPC; + private int length; + private int nameIndex; + private int descIndex; + private int index; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getNameIndex() { + return nameIndex; + } + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + public int getDescIndex() { + return descIndex; + } + public void setDescIndex(int descIndex) { + this.descIndex = descIndex; + } + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableTable.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..3dd937aa2f --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + + +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + int index = iter.nextU2toInt(); + int len = iter.nextU4toInt(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.nextU2toInt(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2toInt()); + item.setLength(iter.nextU2toInt()); + item.setNameIndex(iter.nextU2toInt()); + item.setDescIndex(iter.nextU2toInt()); + item.setIndex(iter.nextU2toInt()); + table.addLocalVariableItem(item); + } + return table; + } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Local Variable Table:\n"); + for(LocalVariableItem item : items){ + buffer.append("startPC:"+item.getStartPC()).append(","); + buffer.append("name:"+pool.getUTF8String(item.getNameIndex())).append(","); + buffer.append("desc:"+pool.getUTF8String(item.getDescIndex())).append(","); + buffer.append("slotIndex:"+ item.getIndex()).append("\n"); + } + buffer.append("\n"); + return buffer.toString(); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/StackMapTable.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..ef046cdfc2 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + + +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; + +public class StackMapTable extends AttributeInfo{ + + private String originalCode; + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static StackMapTable parse(ByteCodeIterator iter){ + int index = iter.nextU2toInt(); + int len = iter.nextU4toInt(); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.nextUxToHexString(len); + t.setOriginalCode(code); + + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java index 82eee82fb5..7135ef9bcb 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java @@ -1,10 +1,11 @@ package com.github.miniyk2012.coding2017.coderising.jvm.clz; -import assignments.jvm.field.Field; -import assignments.jvm.method.Method; + import com.github.miniyk2012.coding2017.coderising.jvm.constant.ClassInfo; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.field.Field; +import com.github.miniyk2012.coding2017.coderising.jvm.method.Method; import java.util.ArrayList; import java.util.List; diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java index 017e6cd8bc..54d0854ba7 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java @@ -1,9 +1,9 @@ package com.github.miniyk2012.coding2017.coderising.jvm.field; -import assignments.jvm.constant.ConstantPool; -import assignments.jvm.constant.UTF8Info; -import assignments.jvm.loader.ByteCodeIterator; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.UTF8Info; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; public class Field { private int accessFlag; @@ -32,10 +32,10 @@ public String toString() { public static Field parse(ConstantPool pool, ByteCodeIterator iter){ - int accessFlag = iter.nextU2ToInt(); - int nameIndex = iter.nextU2ToInt(); - int descIndex = iter.nextU2ToInt(); - int attribCount = iter.nextU2ToInt(); + int accessFlag = iter.nextU2toInt(); + int nameIndex = iter.nextU2toInt(); + int descIndex = iter.nextU2toInt(); + int attribCount = iter.nextU2toInt(); //System.out.println("field attribute count:"+ attribCount); Field f = new Field(accessFlag, nameIndex, descIndex,pool); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java index 73eb2fc1ff..ef2a984ffa 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java @@ -24,6 +24,10 @@ public int nextU2toInt() { return Util.byteToInt(u2); } + public int nextU4toInt() { + return assignments.jvm.util.Util.byteToInt(new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] }); + } + /** * 读取n个字节,并编码成UTF-8输出,point自动增加 * @param n @@ -31,6 +35,10 @@ public int nextU2toInt() { */ public String readUtf8(int n) { + if (point + n >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + byte[] info = Arrays.copyOfRange(codes, point, point+n); String utf8; try { @@ -63,6 +71,20 @@ public void seek(int n) { point = n; } + public String nextU4ToHexString() { + return assignments.jvm.util.Util.byteToHexString((new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[point++]; + } + return assignments.jvm.util.Util.byteToHexString(tmp).toLowerCase(); + + } + public static void main(String[] args) throws UnsupportedEncodingException { byte[] codes = {0x00, 0x34, 0x00}; ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java index 7b84a15899..2638010915 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java @@ -1,9 +1,12 @@ package com.github.miniyk2012.coding2017.coderising.jvm.loader; + import com.github.miniyk2012.coding2017.coderising.jvm.clz.AccessFlag; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex; import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; +import com.github.miniyk2012.coding2017.coderising.jvm.field.Field; +import com.github.miniyk2012.coding2017.coderising.jvm.method.Method; public class ClassFileParser { @@ -12,7 +15,12 @@ public ClassFile parse(byte[] codes) { ClassFile clzFile = new ClassFile(); ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes); - byteCodeIterator.skip(4); // skip magic + // byteCodeIterator.skip(4); // skip magic number + String magicNumber = byteCodeIterator.nextU4ToHexString(); + + if (!"cafebabe".equals(magicNumber)) { + return null; + } int minorVersion = byteCodeIterator.nextU2toInt(); int majorVersion = byteCodeIterator.nextU2toInt(); ConstantPool constantPool = parseConstantPool(byteCodeIterator); @@ -24,6 +32,8 @@ public ClassFile parse(byte[] codes) { clzFile.setConstPool(constantPool); clzFile.setAccessFlag(accessFlag); clzFile.setClassIndex(classIndex); + + parseInterfaces(byteCodeIterator); return clzFile; } @@ -55,6 +65,38 @@ protected ConstantPool parseConstantPool(ByteCodeIterator iter) { return constantPool; } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2toInt(); + + System.out.println("interfaceCount:" + interfaceCount); + for (int i=0; i Date: Wed, 19 Apr 2017 07:47:08 +0800 Subject: [PATCH 03/16] =?UTF-8?q?little=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/coderising/jvm/loader/ClassFileParser.java | 2 ++ .../coding2017/coderising/jvm/method/Method.java | 8 +++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java index 2638010915..2cdfb950af 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java @@ -34,6 +34,8 @@ public ClassFile parse(byte[] codes) { clzFile.setClassIndex(classIndex); parseInterfaces(byteCodeIterator); + parseFileds(clzFile, byteCodeIterator); + parseMethods(clzFile, byteCodeIterator); return clzFile; } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java index e97bc6ad1c..3e08abc298 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java @@ -9,7 +9,7 @@ import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; public class Method { - + private int accessFlag; private int nameIndex; private int descriptorIndex; @@ -45,11 +45,9 @@ public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorInd this.descriptorIndex = descriptorIndex; } + - - - -public String toString() { + public String toString() { ConstantPool pool = this.clzFile.getConstantPool(); StringBuilder buffer = new StringBuilder(); From ade5c10ad39fe4e397fb35fc558c5fc9aeff6181 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Wed, 19 Apr 2017 22:32:05 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E4=B8=AD=E7=BC=80=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/stack/expr/InfixExpr.java | 8 +++++++- .../coding2017/basic/stack/expr/InfixExprTest.java | 9 ++++++++- .../coding2017/coderising/jvm/field/Field.java | 3 --- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java index 92727ce984..69d1b41a0e 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java @@ -1,5 +1,6 @@ package com.github.miniyk2012.coding2017.basic.stack.expr; +import java.util.EmptyStackException; import java.util.LinkedList; import java.util.List; import java.util.Stack; @@ -61,11 +62,16 @@ public float evaluate() { operatorStack.push(t); } else { Token preT = operatorStack.peek(); - if ((preT.value).priority >= ((Operator)t.value).priority) { + while (preT.value.priority >= ((Operator)t.value).priority) { Token number2 = numberStack.pop(); Token number1 = numberStack.pop(); operatorStack.pop(); numberStack.push(evaluate(preT, number1, number2)); + try { + preT = operatorStack.peek(); + } catch (EmptyStackException e) { + break; + } } operatorStack.push(t); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java index a14953535d..5906221e79 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java @@ -19,6 +19,10 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2"); + Assert.assertEquals(2.0, expr.evaluate(), 0.001f); + } { InfixExpr expr = new InfixExpr("2+3"); Assert.assertEquals(5.0, expr.evaluate(), 0.001f); @@ -50,7 +54,10 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50-20/10/2*4"); Assert.assertEquals(26, expr.evaluate(), 0.001f); } - + { + InfixExpr expr = new InfixExpr("10-30+50-20/1+10"); + Assert.assertEquals(20, expr.evaluate(), 0.001f); + } } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java index 54d0854ba7..d89b31c87c 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java @@ -9,9 +9,6 @@ public class Field { private int accessFlag; private int nameIndex; private int descriptorIndex; - - - private ConstantPool pool; public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { From 7e0cab0221991b754acdeffa5c40cd9d977ebe1b Mon Sep 17 00:00:00 2001 From: thomas_young Date: Sun, 30 Apr 2017 19:14:17 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E8=A1=A5=E4=BD=9C=E4=B8=9A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/attr/CodeAttr.java | 9 +++-- .../coderising/jvm/attr/LineNumberTable.java | 19 +++++++++- .../jvm/attr/LocalVariableTable.java | 38 +++++++++---------- .../coderising/jvm/field/Field.java | 8 ++-- .../jvm/loader/ClassFileParser.java | 9 +---- .../coderising/jvm/method/Method.java | 31 ++++++++------- .../jvm/test/ClassFileloaderTest.java | 2 +- 7 files changed, 67 insertions(+), 49 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java index e6b7da9bb6..6c92bd0cf2 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -39,7 +39,7 @@ public void setLocalVariableTable(LocalVariableTable t) { this.localVarTable = t; } -public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + public static CodeAttr parse_V2(ClassFile clzFile, ByteCodeIterator iter){ int attrNameIndex = iter.nextU2toInt(); int attrLen = iter.nextU4toInt(); @@ -51,7 +51,7 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ System.out.println(code); - //ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); + // ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code); @@ -95,7 +95,10 @@ else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ return codeAttr; } - + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + + return null; + } public String toString(ConstantPool pool){ StringBuilder buffer = new StringBuilder(); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java index 5461518d3d..75891b7acc 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java @@ -33,7 +33,7 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } - public static LineNumberTable parse(ByteCodeIterator iter){ + public static LineNumberTable parse_V2(ByteCodeIterator iter){ int index = iter.nextU2toInt(); int len = iter.nextU4toInt(); @@ -50,6 +50,23 @@ public static LineNumberTable parse(ByteCodeIterator iter){ } return table; } + + public static LineNumberTable parse(ByteCodeIterator iter){ + int nameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU4toInt(); + int tableLen = iter.nextU2toInt(); + LineNumberTable table = new LineNumberTable(nameIndex, attrLen); + + for (int i=0; i items = new ArrayList(); + List items = new ArrayList<>(); public LocalVariableTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); @@ -19,26 +19,24 @@ public LocalVariableTable(int attrNameIndex, int attrLen) { private void addLocalVariableItem(LocalVariableItem item) { this.items.add(item); } - + public static LocalVariableTable parse(ByteCodeIterator iter){ - - int index = iter.nextU2toInt(); - int len = iter.nextU4toInt(); - - LocalVariableTable table = new LocalVariableTable(index,len); - - int itemLen = iter.nextU2toInt(); - - for(int i=1; i<=itemLen; i++){ - LocalVariableItem item = new LocalVariableItem(); - item.setStartPC(iter.nextU2toInt()); - item.setLength(iter.nextU2toInt()); - item.setNameIndex(iter.nextU2toInt()); - item.setDescIndex(iter.nextU2toInt()); - item.setIndex(iter.nextU2toInt()); - table.addLocalVariableItem(item); - } - return table; + int nameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU4toInt(); + LocalVariableTable table = new LocalVariableTable(nameIndex, attrLen); + int tableLen = iter.nextU2toInt(); + + for(int i=0; i 0){ throw new RuntimeException("Field Attribute has not been implemented"); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java index 2cdfb950af..f3457e1ae5 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java @@ -80,23 +80,18 @@ private void parseInterfaces(ByteCodeIterator iter) { private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { int fieldCount = iter.nextU2toInt(); - - for (int i = 1; i <= fieldCount; i++) { + for (int i =0; i Date: Sun, 30 Apr 2017 21:08:21 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E6=B1=82=E5=80=BC=20PrefixExpr.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/stack/expr/ExprUtil.java | 38 +++++++++++++ .../basic/stack/expr/InfixToPostfix.java | 14 +++++ .../basic/stack/expr/PostfixExpr.java | 18 ++++++ .../basic/stack/expr/PostfixExprTest.java | 41 +++++++++++++ .../basic/stack/expr/PrefixExpr.java | 51 +++++++++++++++++ .../basic/stack/expr/PrefixExprTest.java | 45 +++++++++++++++ .../coding2017/basic/stack/expr/Token.java | 54 ++++++++++++++++++ .../basic/stack/expr/TokenParser.java | 57 +++++++++++++++++++ .../basic/stack/expr/TokenParserTest.java | 39 +++++++++++++ 9 files changed, 357 insertions(+) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java new file mode 100644 index 0000000000..293117b3f6 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java @@ -0,0 +1,38 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +/** + * Created by thomas_young on 30/4/2017. + */ +public class ExprUtil { + + /** + * 求值 + * @param operand1 操作数1 + * @param operator 操作符 + * @param operand2 操作数2 + * @return Token表示的值 + */ + public static Token evalute(Token operand1, Token operator, Token operand2) { + float resultValue; + switch (operator.value) { + case "+": { + resultValue = operand1.getFloatValue() + operand2.getFloatValue(); + break; + } + case "-": { + resultValue = operand1.getFloatValue() - operand2.getFloatValue(); + break; + } + case "*": { + resultValue = operand1.getFloatValue() * operand2.getFloatValue(); + break; + } + case "/": { + resultValue = operand1.getFloatValue() / operand2.getFloatValue(); + break; + } + default: throw new RuntimeException("不支持的运算符:" + operator.value); + } + return new Token(Token.NUMBER, String.valueOf(resultValue)); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..5ae9bfedab --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,14 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..207640d6bd --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,18 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..24aa8f44f5 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + PostfixExpr expr = new PostfixExpr("6 5 2 3 + 8 * + 3 + *"); + Assert.assertEquals(288, expr.evaluate(),0.0f); + } + { + //9+(3-1)*3+10/2 + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + Assert.assertEquals(20, expr.evaluate(),0.0f); + } + + { + //10-2*3+50 + PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); + Assert.assertEquals(54, expr.evaluate(),0.0f); + } + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..20f0a15e9c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,51 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +/** + https://en.wikipedia.org/wiki/Polish_notation + Scan the given prefix expression from right to left + for each symbol + { + if operand then + push onto stack + if operator then + { + operand1=pop stack + operand2=pop stack + compute operand1 operator operand2 + push result onto stack + } + } + return top of stack as result + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Collections.reverse(tokens); + Stack operandStack = new Stack<>(); + for (Token token: tokens) { + if (token.isNumber()) { + operandStack.push(token); + } else { + Token operand1 = operandStack.pop(); + Token operand2 = operandStack.pop(); + Token result = ExprUtil.evalute(operand1, token, operand2); + operandStack.push(result); + } + } + + return operandStack.pop().getFloatValue(); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..4a0a0955b3 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + // 2*3+4*5 + PrefixExpr expr = new PrefixExpr("+ * 2 3* 4 5"); + Assert.assertEquals(26, expr.evaluate(),0.001f); + } + { + // 4*2 + 6+9*2/3 -8 + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + Assert.assertEquals(12, expr.evaluate(),0.001f); + } + { + //(3+4)*5-6 + PrefixExpr expr = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29, expr.evaluate(),0.001f); + } + { + //1+((2+3)*4)-5 + PrefixExpr expr = new PrefixExpr("- + 1 * + 2 3 4 5"); + Assert.assertEquals(16, expr.evaluate(),0.001f); + } + + + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java new file mode 100644 index 0000000000..afaa4a8a41 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java @@ -0,0 +1,54 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Token { + public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + private static final Map priorities = new HashMap<>(); + static { + priorities.put("+", 1); + priorities.put("-", 1); + priorities.put("*", 2); + priorities.put("/", 2); + } + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + public Token(int type, String value){ + this.type = type; + this.value = value; + } + + public boolean isNumber() { + return type == NUMBER; + } + + public boolean isOperator() { + return type == OPERATOR; + } + + public float getFloatValue() { + return Float.parseFloat(value); + } + + public int getIntValue() { + return Integer.parseInt(value); + } + public String toString(){ + return value; + } + + public boolean hasHigherPriority(Token t){ + if(!this.isOperator() && !t.isOperator()){ + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + + + +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..aa4e0560cf --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + + public List parse(String expr) { + List tokens = new ArrayList<>(); + + int i = 0; + + while (i < expr.length()) { + + char c = expr.charAt(i); + + if (isOperator(c)) { + + Token t = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(t); + i++; + + } else if (Character.isDigit(c)) { + + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token t = new Token(Token.NUMBER, value); + tokens.add(t); + i = nextOperatorIndex; + + } else{ + System.out.println("char :["+c+"] is not number or operator,ignore"); + i++; + } + + } + return tokens; + } + + private int indexOfNextOperator(int i, String expr) { + + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + + } + + private boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..92b54d0bb7 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TokenParserTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse("300*20+12*5-20/4"); + float delta = 0.0001f; + Assert.assertEquals(300, tokens.get(0).getFloatValue(), delta); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getFloatValue(), delta); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getFloatValue(), delta); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getFloatValue(), delta); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getFloatValue(), delta); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getFloatValue(), delta); + } + +} From 3cc449528a99c7e4a3d5456b526f13ad36a0d07c Mon Sep 17 00:00:00 2001 From: thomas_young Date: Sun, 30 Apr 2017 21:20:14 +0800 Subject: [PATCH 07/16] =?UTF-8?q?=E5=90=8E=E7=BC=80=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E6=B1=82=E5=80=BCPostfixExpr.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/PostfixExpr.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java index 207640d6bd..6475450e4c 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java @@ -3,6 +3,26 @@ import java.util.List; import java.util.Stack; + +/** + https://en.wikipedia.org/wiki/Reverse_Polish_notation + + While there are input tokens left + Read the next token from input. + If the token is a value + Push it onto the stack. + Otherwise, the token is an operator (operator here includes both operators and functions). + It is already known that the operator takes n arguments. + If there are fewer than n values on the stack + (Error) The user has not input sufficient values in the expression. + Else, Pop the top n values from the stack. + Evaluate the operator, with the values as arguments. + Push the returned results, if any, back onto the stack. + If there is only one value in the stack + That value is the result of the calculation. + Otherwise, there are more values in the stack + (Error) The user input has too many values. + */ public class PostfixExpr { String expr = null; @@ -11,7 +31,20 @@ public PostfixExpr(String expr) { } public float evaluate() { - return 0.0f; + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack operandStack = new Stack<>(); + for (Token token: tokens) { + if (token.isNumber()) { + operandStack.push(token); + } else { + Token operand1 = operandStack.pop(); + Token operand2 = operandStack.pop(); + Token result = ExprUtil.evalute(operand2, token, operand1); + operandStack.push(result); + } + } + return operandStack.pop().getFloatValue(); } From 431ffd26efae1ce785616310b70999a2f47d37f0 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Sun, 30 Apr 2017 22:28:41 +0800 Subject: [PATCH 08/16] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B8=AD=E7=BC=80?= =?UTF-8?q?=E8=BD=AC=E5=90=8E=E7=BC=80=E8=A1=A8=E8=BE=BE=E5=BC=8FInfixToPo?= =?UTF-8?q?stfix.java,=E5=B9=B6=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8BInfixToPostfixTest.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/stack/expr/ExprUtil.java | 15 +++++ .../basic/stack/expr/InfixToPostfix.java | 49 ++++++++++++-- .../basic/stack/expr/InfixToPostfixTest.java | 67 +++++++++++++++++++ 3 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java index 293117b3f6..e69042a583 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java @@ -1,5 +1,7 @@ package com.github.miniyk2012.coding2017.basic.stack.expr; +import java.util.List; + /** * Created by thomas_young on 30/4/2017. */ @@ -35,4 +37,17 @@ public static Token evalute(Token operand1, Token operator, Token operand2) { } return new Token(Token.NUMBER, String.valueOf(resultValue)); } + + public static String tokens2String(List tokens) { + StringBuffer buffer = new StringBuffer(); + int i = 0; + for (Token token: tokens) { + if (i != tokens.size()-1) + buffer.append(token.toString()+" "); + else + buffer.append(token.toString()); + i++; + } + return buffer.toString(); + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java index 5ae9bfedab..d99971e5b6 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java @@ -1,14 +1,53 @@ package com.github.miniyk2012.coding2017.basic.stack.expr; +import java.util.EmptyStackException; +import java.util.LinkedList; import java.util.List; +import java.util.Stack; +/** + * Shunting-yard algorithm + * https://en.wikipedia.org/wiki/Shunting-yard_algorithm + 初始化一个运算符栈和一个输出队列 + 不断读取token + 如果token是一个数 + 将其放入输出队列 + 如果token是一个运算符o1 + while栈顶部有运算符o2: + 如果o1的优先级小于等于o2,把o2取出放到输出队列 + 最后push(o1) + 将栈中的操作符逐个出栈放到输出队列 + */ public class InfixToPostfix { public static List convert(String expr) { - - return null; + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack operatorStack = new Stack<>(); + List outputTokens = new LinkedList<>(); + for (Token token: tokens) { + if (token.isNumber()) { + outputTokens.add(token); + } else { + while (true) { + try { + Token o2 = operatorStack.peek(); + if (!token.hasHigherPriority(o2)) { + operatorStack.pop(); + outputTokens.add(o2); + } else { + break; + } + } catch (EmptyStackException e) { + break; + } + } + operatorStack.push(token); + } + } + while (!operatorStack.isEmpty()) { + outputTokens.add(operatorStack.pop()); + } + return outputTokens; } - - - } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..b363e58e35 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,67 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +import java.util.List; + +/** +* InfixToPostfix Tester. +* +* @author +* @since
Apr 30, 2017
+* @version 1.0 +*/ +public class InfixToPostfixTest { + + @Before + public void before() throws Exception { + } + + @After + public void after() throws Exception { + } + + /** + * + * Method: convert(String expr) + * + */ + @Test + public void testConvert() throws Exception { + { + String infixExpr = "3+4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("3 4 +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 * 3 + 4 * 6"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 * 4 6 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 * 3 / 4 * 6"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 * 4 / 6 *", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 + 3 * 4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 4 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "3+2*3+4*5"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("3 2 3 * + 4 5 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1-3+5-2/1/2*4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 - 5 + 2 1 / 2 / 4 * -", ExprUtil.tokens2String(tokens)); + } + } + + +} From 4dd28500455e015482d38943de0e85946e5555f9 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Mon, 1 May 2017 09:32:27 +0800 Subject: [PATCH 09/16] =?UTF-8?q?=E5=AE=8C=E6=88=90Method=E5=92=8CField?= =?UTF-8?q?=E7=9A=84parse(jvm=E7=AC=AC3=E6=AC=A1=E4=BD=9C=E4=B8=9A)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/attr/CodeAttr.java | 39 ++++++++++++++++--- .../coderising/jvm/method/Method.java | 22 +++++++++-- .../jvm/test/ClassFileloaderTest.java | 4 +- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java index 6c92bd0cf2..29feb072f7 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -53,7 +53,7 @@ public static CodeAttr parse_V2(ClassFile clzFile, ByteCodeIterator iter){ // ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); - CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); int exceptionTableLen = iter.nextU2toInt(); //TODO 处理exception @@ -74,7 +74,6 @@ public static CodeAttr parse_V2(ClassFile clzFile, ByteCodeIterator iter){ iter.skip(-2); //line item table if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ - LineNumberTable t = LineNumberTable.parse(iter); codeAttr.setLineNumberTable(t); } @@ -89,15 +88,45 @@ else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ else{ throw new RuntimeException("Need code to process " + subAttrName); } - - } return codeAttr; } public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + int attributeNameIndex = iter.nextU2toInt(); + int attributeLength = iter.nextU4toInt(); + int maxStack = iter.nextU2toInt(); + int maxLocals = iter.nextU2toInt(); + int codeLength = iter.nextU4toInt(); + + String code = iter.nextUxToHexString(codeLength); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + + int exceptionTableLen = iter.nextU2toInt(); + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + } - return null; + int attributesCount = iter.nextU2toInt(); + for (int i=0; i Date: Mon, 1 May 2017 14:08:45 +0800 Subject: [PATCH 10/16] little improve --- .../coding2017/coderising/jvm/attr/LineNumberTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java index 75891b7acc..207000e7c1 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/LineNumberTable.java @@ -7,7 +7,7 @@ public class LineNumberTable extends AttributeInfo { - List items = new ArrayList(); + List items = new ArrayList<>(); private static class LineNumberItem{ int startPC; From 7fdcbf5a3a2cb74851214b7f56ffee5ef1cdd5ab Mon Sep 17 00:00:00 2001 From: thomas_young Date: Mon, 1 May 2017 15:35:23 +0800 Subject: [PATCH 11/16] =?UTF-8?q?=E6=95=B4=E7=90=86cmd=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/queue/CircleQueue.java | 5 + .../coding2017/basic/queue/Josephus.java | 20 +++ .../coding2017/basic/queue/JosephusTest.java | 27 ++++ .../coding2017/basic/queue/Queue.java | 61 +++++++++ .../basic/queue/QueueWithTwoStacks.java | 40 ++++++ .../coderising/jvm/attr/CodeAttr.java | 81 +++-------- .../coderising/jvm/clz/ClassFile.java | 14 +- .../coderising/jvm/cmd/BiPushCmd.java | 22 +++ .../coderising/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++++ .../coderising/jvm/cmd/CommandParser.java | 85 ++++++++++++ .../coderising/jvm/cmd/GetFieldCmd.java | 22 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 20 +++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 22 +++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../coding2017/coderising/jvm/cmd/LdcCmd.java | 30 ++++ .../coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../coderising/jvm/cmd/NoOperandCmd.java | 23 ++++ .../coderising/jvm/cmd/OneOperandCmd.java | 28 ++++ .../coderising/jvm/cmd/PutFieldCmd.java | 20 +++ .../coderising/jvm/cmd/TwoOperandCmd.java | 64 +++++++++ .../coderising/jvm/method/Method.java | 6 +- .../jvm/print/ClassFilePrinter.java | 42 ++++++ .../jvm/print/ConstantPoolPrinter.java | 19 +++ .../jvm/test/ClassFileloaderTest.java | 84 ++++++++++++ 24 files changed, 836 insertions(+), 68 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/JosephusTest.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Queue.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..104ca0c92f --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java @@ -0,0 +1,5 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +public class CircleQueue { + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..199a08628c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java @@ -0,0 +1,20 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 知道最后一个人留下来 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + + return null; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/JosephusTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..6c7bf78419 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Queue.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Queue.java new file mode 100644 index 0000000000..7db4923e15 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + private Node first; + private Node last; + private int size; + + + private static class Node { + private E item; + private Node next; + } + + + public Queue() { + first = null; + last = null; + size = 0; + } + + + public boolean isEmpty() { + return first == null; + } + + public int size() { + return size; + } + + + + public void enQueue(E data) { + Node oldlast = last; + last = new Node(); + last.item = data; + last.next = null; + if (isEmpty()) { + first = last; + } + else{ + oldlast.next = last; + } + size++; + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue underflow"); + } + E item = first.item; + first = first.next; + size--; + if (isEmpty()) { + last = null; + } + return item; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..4f7ba31387 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,40 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + + + public boolean isEmpty() { + return false; + } + + + + public int size() { + return -1; + } + + + + public void enQueue(E item) { + + } + + public E deQueue() { + return null; + } + + + } + diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java index 29feb072f7..abc89a94d0 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -2,6 +2,7 @@ import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.ByteCodeCommand; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; @@ -14,21 +15,27 @@ public String getCode() { return code; } - //private ByteCodeCommand[] cmds ; - //public ByteCodeCommand[] getCmds() { - // return cmds; - //} + private ByteCodeCommand[] cmds ; + public ByteCodeCommand[] getCmds() { + return cmds; + } private LineNumberTable lineNumTable; private LocalVariableTable localVarTable; private StackMapTable stackMapTable; - public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code /*ByteCodeCommand[] cmds*/) { + public CodeAttr(int attrNameIndex, + int attrLen, + int maxStack, + int maxLocals, + int codeLen, + String code, + ByteCodeCommand[] cmds) { super(attrNameIndex, attrLen); this.maxStack = maxStack; this.maxLocals = maxLocals; this.codeLen = codeLen; this.code = code; - //this.cmds = cmds; + this.cmds = cmds; } public void setLineNumberTable(LineNumberTable t) { @@ -38,60 +45,7 @@ public void setLineNumberTable(LineNumberTable t) { public void setLocalVariableTable(LocalVariableTable t) { this.localVarTable = t; } - - public static CodeAttr parse_V2(ClassFile clzFile, ByteCodeIterator iter){ - - int attrNameIndex = iter.nextU2toInt(); - int attrLen = iter.nextU4toInt(); - int maxStack = iter.nextU2toInt(); - int maxLocals = iter.nextU2toInt(); - int codeLen = iter.nextU4toInt(); - - String code = iter.nextUxToHexString(codeLen); - - System.out.println(code); - - // ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); - - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); - - int exceptionTableLen = iter.nextU2toInt(); - //TODO 处理exception - if(exceptionTableLen>0){ - String exTable = iter.nextUxToHexString(exceptionTableLen); - System.out.println("Encountered exception table , just ignore it :" + exTable); - - } - - - int subAttrCount = iter.nextU2toInt(); - - for(int x=1; x<=subAttrCount; x++){ - int subAttrIndex = iter.nextU2toInt(); - String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); - - //已经向前移动了U2, 现在退回去。 - iter.skip(-2); - //line item table - if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ - LineNumberTable t = LineNumberTable.parse(iter); - codeAttr.setLineNumberTable(t); - } - else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ - LocalVariableTable t = LocalVariableTable.parse(iter); - codeAttr.setLocalVariableTable(t); - } - else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ - StackMapTable t = StackMapTable.parse(iter); - codeAttr.setStackMapTable(t); - } - else{ - throw new RuntimeException("Need code to process " + subAttrName); - } - } - - return codeAttr; - } + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int attributeNameIndex = iter.nextU2toInt(); int attributeLength = iter.nextU4toInt(); @@ -100,7 +54,7 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int codeLength = iter.nextU4toInt(); String code = iter.nextUxToHexString(codeLength); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, null); int exceptionTableLen = iter.nextU2toInt(); if(exceptionTableLen>0){ @@ -132,9 +86,9 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ public String toString(ConstantPool pool){ StringBuilder buffer = new StringBuilder(); buffer.append("Code:").append(code).append("\n"); - /*for(int i=0;i codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..aebfd87058 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; + +import java.util.List; + + +public class CommandParser { + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + + + return null; + } + + private static void calcuateOffset(List cmds) { + + int offset = 0; + for (ByteCodeCommand cmd : cmds) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + + } + + private static class CommandIterator { + String codes = null; + int pos = 0; + + CommandIterator(String codes) { + this.codes = codes; + } + + public boolean hasNext() { + return pos < this.codes.length(); + } + + public String next2CharAsString() { + String result = codes.substring(pos, pos + 2); + pos += 2; + return result; + } + + public int next2CharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..f996abe54c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..5627e5efb0 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..0ff685b960 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..f9688b128b --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..4e8e535bcc --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantInfo; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..6bcac6b662 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..d63e47ae17 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + + public int getLength(){ + return 1; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..00e7b09a67 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + private int operand; + + public OneOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + public int getOperand() { + + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + + } + public int getLength(){ + return 2; + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..bb2f8f2efd --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..2f7fd67303 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,64 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; + +public abstract class TwoOperandCmd extends ByteCodeCommand{ + + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + public int getOprand2() { + return oprand2; + } + + public TwoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + public int getIndex(){ + int oprand1 = this.getOprand1(); + int oprand2 = this.getOprand2(); + int index = oprand1 << 8 | oprand2; + return index; + } + + protected String getOperandAsClassInfo(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ConstantInfo constInfo = this.getConstantInfo(index); + MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + + protected String getOperandAsField(ConstantPool pool){ + int index = getIndex(); + + String codeTxt = getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + public int getLength(){ + return 3; + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java index f7e09075f5..249591d598 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java @@ -4,8 +4,8 @@ import com.github.miniyk2012.coding2017.coderising.jvm.attr.AttributeInfo; import com.github.miniyk2012.coding2017.coderising.jvm.attr.CodeAttr; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.ByteCodeCommand; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; -import com.github.miniyk2012.coding2017.coderising.jvm.constant.UTF8Info; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; public class Method { @@ -109,4 +109,8 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return method; } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..c52df283b0 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,42 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.print; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ClassFileLoader; + +public class ClassFilePrinter { + ClassFile clzFile = null; + public ClassFilePrinter(ClassFile clzFile){ + this.clzFile = clzFile; + } + + public void print(){ + + if(clzFile.getAccessFlag().isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ clzFile.getClassName()); + + System.out.println("Super Class Name:"+ clzFile.getSuperClassName()); + + System.out.println("minor version:" + clzFile.getMinorVersion()); + + System.out.println("major version:" + clzFile.getMinorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + } + + public static void main(String[] args){ + String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..4415a7236c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,19 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.print; + + +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java index 0675712b1f..81487f8f99 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java @@ -2,6 +2,10 @@ import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.BiPushCmd; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.ByteCodeCommand; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.OneOperandCmd; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.TwoOperandCmd; import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; import com.github.miniyk2012.coding2017.coderising.jvm.field.Field; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ClassFileLoader; @@ -248,4 +252,84 @@ private void assertMethodEquals(ConstantPool pool, Method m , String expectedNam Assert.assertEquals(expectedCode, code); } + + /** + * 下面是第四次作业Cmd的测试用例 + */ + + @Test + public void testByteCodeCommand(){ + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + ByteCodeCommand[] cmds = initMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: invokespecial #12", cmds[1]); + assertOpCodeEquals("4: aload_0", cmds[2]); + assertOpCodeEquals("5: aload_1", cmds[3]); + assertOpCodeEquals("6: putfield #15", cmds[4]); + assertOpCodeEquals("9: aload_0", cmds[5]); + assertOpCodeEquals("10: iload_2", cmds[6]); + assertOpCodeEquals("11: putfield #17", cmds[7]); + assertOpCodeEquals("14: return", cmds[8]); + } + + { + Method setNameMethod = this.clzFile.getMethod("setName", "(Ljava/lang/String;)V"); + ByteCodeCommand [] cmds = setNameMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: aload_1", cmds[1]); + assertOpCodeEquals("2: putfield #15", cmds[2]); + assertOpCodeEquals("5: return", cmds[3]); + + } + + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + ByteCodeCommand [] cmds = sayHelloMethod.getCmds(); + + assertOpCodeEquals("0: getstatic #28", cmds[0]); + assertOpCodeEquals("3: ldc #34", cmds[1]); + assertOpCodeEquals("5: invokevirtual #36", cmds[2]); + assertOpCodeEquals("8: return", cmds[3]); + + } + + { + Method mainMethod = this.clzFile.getMainMethod(); + + ByteCodeCommand [] cmds = mainMethod.getCmds(); + + assertOpCodeEquals("0: new #1", cmds[0]); + assertOpCodeEquals("3: dup", cmds[1]); + assertOpCodeEquals("4: ldc #43", cmds[2]); + assertOpCodeEquals("6: bipush 29", cmds[3]); + assertOpCodeEquals("8: invokespecial #45", cmds[4]); + assertOpCodeEquals("11: astore_1", cmds[5]); + assertOpCodeEquals("12: aload_1", cmds[6]); + assertOpCodeEquals("13: invokevirtual #47", cmds[7]); + assertOpCodeEquals("16: return", cmds[8]); + } + + } + + private void assertOpCodeEquals(String expected, ByteCodeCommand cmd){ + + String acctual = cmd.getOffset()+": "+cmd.getReadableCodeText(); + + if(cmd instanceof OneOperandCmd){ + if(cmd instanceof BiPushCmd){ + acctual += " " + ((OneOperandCmd)cmd).getOperand(); + } else{ + acctual += " #" + ((OneOperandCmd)cmd).getOperand(); + } + } + if(cmd instanceof TwoOperandCmd){ + acctual += " #" + ((TwoOperandCmd)cmd).getIndex(); + } + Assert.assertEquals(expected, acctual); + } + + } From bfed3effd277355ca225608d782eb2ecfc341445 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Mon, 1 May 2017 21:29:09 +0800 Subject: [PATCH 12/16] =?UTF-8?q?Jvm=E7=AC=AC=E5=9B=9B=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=EF=BC=9Acmds=E5=91=BD=E4=BB=A4=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/LinkedList.java | 2 +- .../coderising/array/ArrayUtil.java | 2 +- .../coderising/jvm/attr/CodeAttr.java | 9 ++- .../coderising/jvm/clz/ClassFile.java | 10 ++- .../coderising/jvm/cmd/ByteCodeCommand.java | 8 +-- .../coderising/jvm/cmd/CommandParser.java | 66 ++++++++++++++++++- .../jvm/loader/ByteCodeIterator.java | 6 +- .../jvm/loader/ClassFileParser.java | 2 +- .../coderising/jvm/method/Method.java | 43 ++++-------- .../jvm/print/ConstantPoolPrinter.java | 2 +- .../jvm/test/ClassFileloaderTest.java | 13 +++- 11 files changed, 112 insertions(+), 51 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java index 0ba1d9861c..2fdc34fc25 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java @@ -318,7 +318,7 @@ public LinkedList intersection(LinkedList list){ LinkedList cList = new LinkedList(); - // TODO:为了方便起见,先各自复制并去重,虽然效率不高,以后有时间再优化 + // 为了方便起见,先各自复制并去重,虽然效率不高,以后有时间再优化 LinkedList aList = LinkedList.copy(this); LinkedList bList = LinkedList.copy(list); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java index 41bc6ad344..bedf53dbc9 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java @@ -119,7 +119,7 @@ public int[] fibonacci(int max){ * @return */ public int[] getPrimes(int max){ - // TODO 使用筛法,写的不好,有待改善 + // TODO 使用筛法,写的不好,有待改善,见《敏捷开发》一书,我有空就重构 if (max <= 2) return new int[0]; List list = new ArrayList<>(); int i; diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java index abc89a94d0..640250343f 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -3,6 +3,7 @@ import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.cmd.ByteCodeCommand; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.CommandParser; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; @@ -54,7 +55,8 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int codeLength = iter.nextU4toInt(); String code = iter.nextUxToHexString(codeLength); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, null); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, cmds); int exceptionTableLen = iter.nextU2toInt(); if(exceptionTableLen>0){ @@ -98,8 +100,5 @@ private void setStackMapTable(StackMapTable t) { this.stackMapTable = t; } - - - - + } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java index 745f98636e..54aaf6d95e 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java @@ -84,11 +84,17 @@ public String getSuperClassName(){ } public Method getMethod(String methodName, String paramAndReturnType){ + for (Method method: methods) { + String mName = method.getMethodName(); + String desc = method.getDescriptor(); + if (mName.equals(methodName) && desc.equals(paramAndReturnType)) { + return method; + } + } return null; } public Method getMainMethod(){ - - return null; + return getMethod("main", "([Ljava/lang/String;)V"); } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java index bb6cbb8244..cc83c38702 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java @@ -10,11 +10,11 @@ public abstract class ByteCodeCommand { - String opCode; + String opCode; // 该指令的助记符 ClassFile clzFile; - private int offset; + private int offset; // 该命令在某方法指令中的偏移量 - private static Map codeMap = new HashMap(); + private static Map codeMap = new HashMap(); // 二级制码与助记符的对应关系 static{ codeMap.put("01", "aconst_null"); @@ -102,7 +102,7 @@ public String getOpCode() { return opCode; } - public abstract int getLength(); + public abstract int getLength(); // 以后goto语句要用到 diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java index aebfd87058..a21a9f66a3 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java @@ -2,6 +2,7 @@ import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import java.util.LinkedList; import java.util.List; @@ -44,8 +45,69 @@ public class CommandParser { public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { - - return null; + CommandIterator cIter = new CommandIterator(codes); + List cmds = new LinkedList<>(); + // 将字符串解析为ByteCodeCommand[] + while (cIter.hasNext()) { // todo 重构,1.不应该用这么多的if语句 2.大量重复代码 + String opCode = cIter.next2CharAsString().toUpperCase(); + if (opCode.equalsIgnoreCase(getfield)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(getstatic)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(invokespecial)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(invokevirtual)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(ldc)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(new_object)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(putfield)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(bipush)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(aload_0) + || opCode.equalsIgnoreCase(aload_1) + || opCode.equalsIgnoreCase(aload_2) + || opCode.equalsIgnoreCase(astore_1) + || opCode.equalsIgnoreCase(iload_1) + || opCode.equalsIgnoreCase(iload_2) + || opCode.equalsIgnoreCase(voidreturn) + || opCode.equalsIgnoreCase(dup) + ) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("not implement cmd: " + opCode); + } + + } + calcuateOffset(cmds); + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; } private static void calcuateOffset(List cmds) { diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java index ef2a984ffa..39500bb87c 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java @@ -25,7 +25,7 @@ public int nextU2toInt() { } public int nextU4toInt() { - return assignments.jvm.util.Util.byteToInt(new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] }); + return Util.byteToInt(new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] }); } /** @@ -72,7 +72,7 @@ public void seek(int n) { } public String nextU4ToHexString() { - return assignments.jvm.util.Util.byteToHexString((new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] })); + return Util.byteToHexString((new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] })); } public String nextUxToHexString(int len) { @@ -81,7 +81,7 @@ public String nextUxToHexString(int len) { for (int i = 0; i < len; i++) { tmp[i] = codes[point++]; } - return assignments.jvm.util.Util.byteToHexString(tmp).toLowerCase(); + return Util.byteToHexString(tmp).toLowerCase(); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java index f3457e1ae5..1e7ad606d9 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java @@ -70,7 +70,7 @@ protected ConstantPool parseConstantPool(ByteCodeIterator iter) { private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2toInt(); - System.out.println("interfaceCount:" + interfaceCount); + // System.out.println("interfaceCount:" + interfaceCount); for (int i=0; i Date: Mon, 1 May 2017 22:24:22 +0800 Subject: [PATCH 13/16] little improve --- .../coderising/jvm/cmd/ByteCodeCommand.java | 19 +++++++------------ .../coding2017/coderising/jvm/cmd/LdcCmd.java | 2 +- .../coderising/jvm/cmd/PutFieldCmd.java | 2 -- .../coderising/jvm/cmd/TwoOperandCmd.java | 3 +-- .../coderising/jvm/constant/FieldRefInfo.java | 3 --- .../jvm/print/ClassFilePrinter.java | 4 ++-- .../jvm/print/ConstantPoolPrinter.java | 5 ++--- .../jvm/test/ClassFileloaderTest.java | 19 +++++++++++++++---- 8 files changed, 28 insertions(+), 29 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java index cc83c38702..46d0966ea9 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java @@ -67,10 +67,7 @@ public abstract class ByteCodeCommand { codeMap.put("12", "ldc"); } - - - protected ByteCodeCommand(ClassFile clzFile, String opCode){ this.clzFile = clzFile; @@ -88,25 +85,22 @@ public int getOffset() { public void setOffset(int offset) { this.offset = offset; } + protected ConstantInfo getConstantInfo(int index){ - return this.getClassFile().getConstantPool().getConstantInfo(index); + return getConstantPool().getConstantInfo(index); } protected ConstantPool getConstantPool(){ return this.getClassFile().getConstantPool(); } - - - + public String getOpCode() { return opCode; } public abstract int getLength(); // 以后goto语句要用到 - - - - + + @Override public String toString(){ StringBuffer buffer = new StringBuffer(); @@ -114,12 +108,13 @@ public String toString(){ return buffer.toString(); } + public abstract String toString(ConstantPool pool); public String getReadableCodeText(){ String txt = codeMap.get(opCode); if(txt == null){ - return opCode; + throw new RuntimeException("codeMap don't contain: " + opCode); } return txt; } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java index 4e8e535bcc..1aef5af580 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java @@ -15,7 +15,7 @@ public LdcCmd(ClassFile clzFile, String opCode) { @Override public String toString(ConstantPool pool) { - ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + ConstantInfo info = pool.getConstantInfo(this.getOperand()); String value = "TBD"; if(info instanceof StringInfo){ diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java index bb2f8f2efd..46a878940f 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java @@ -15,6 +15,4 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - - } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java index 2f7fd67303..9cb8173567 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java @@ -39,14 +39,13 @@ public int getIndex(){ protected String getOperandAsClassInfo(ConstantPool pool){ int index = getIndex(); String codeTxt = getReadableCodeText(); - ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + ClassInfo info = (ClassInfo)getConstantInfo(index); return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); } protected String getOperandAsMethod(ConstantPool pool){ int index = getIndex(); String codeTxt = getReadableCodeText(); - ConstantInfo constInfo = this.getConstantInfo(index); MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java index 98c5ced1a9..b69e5aebc6 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java @@ -34,9 +34,6 @@ public String toString(){ public String getClassName(){ ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); - - // UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); - // return utf8Info.getValue(); return classInfo.getClassName(); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java index c52df283b0..b2887df85e 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ClassFilePrinter.java @@ -28,10 +28,10 @@ public void print(){ } public static void main(String[] args){ - String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + String path = ClassFilePrinter.class.getClassLoader().getResource("jvm").getPath(); ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1"; ClassFile clzFile = loader.loadClass(className); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java index fd07affd2e..f3c164be13 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/print/ConstantPoolPrinter.java @@ -8,12 +8,11 @@ public class ConstantPoolPrinter { ConstantPoolPrinter(ConstantPool pool){ this.pool = pool; } + public void print(){ // todo: 实现javap System.out.println("Constant Pool:"); - - - + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java index 52ee7f4426..b2b06459f8 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java @@ -11,10 +11,7 @@ import com.github.miniyk2012.coding2017.coderising.jvm.loader.ClassFileLoader; import com.github.miniyk2012.coding2017.coderising.jvm.method.Method; import com.github.miniyk2012.coding2017.coderising.jvm.util.Util; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.*; import java.util.List; @@ -335,11 +332,25 @@ private void assertOpCodeEquals(String expected, ByteCodeCommand cmd){ * 编写代码时做的一些测试用例 */ @Test + @Ignore public void otherThing() { { // Method的若干方法 Method mainMethod = this.clzFile.getMainMethod(); Assert.assertEquals("main", mainMethod.getMethodName()); Assert.assertEquals("([Ljava/lang/String;)V", mainMethod.getDescriptor()); + System.out.println(mainMethod); + } + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + System.out.println(sayHelloMethod); + } + { + Method setNameMethod = this.clzFile.getMethod("setName", "(Ljava/lang/String;)V"); + System.out.println(setNameMethod); + } + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + System.out.println(initMethod); } } From c4ab820de2a0aff4ca64cb8fc5e27cd55e04f134 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Tue, 2 May 2017 22:14:01 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BA=A6=E7=91=9F?= =?UTF-8?q?=E5=A4=AB=E7=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/queue/CircleQueueTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..a55219fde2 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java @@ -0,0 +1,44 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class CircleQueueTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + CircleQueue queue = new CircleQueue(5); + Assert.assertTrue(queue.isEmpty()); + Assert.assertFalse(queue.isFull()); + + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + queue.enQueue("d"); + queue.enQueue("e"); + + Assert.assertTrue(queue.isFull()); + Assert.assertFalse(queue.isEmpty()); + Assert.assertEquals(5, queue.size()); + + Assert.assertEquals("a", queue.deQueue()); + Assert.assertEquals("b", queue.deQueue()); + Assert.assertEquals("c", queue.deQueue()); + Assert.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} From 148869c724baba2a9b57e535ecbac4aa00a06fc9 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Wed, 3 May 2017 00:13:58 +0800 Subject: [PATCH 15/16] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=B12=E4=B8=AA?= =?UTF-8?q?=E6=A0=88=E6=9E=84=E6=88=90=E7=9A=84=E9=98=9F=E5=88=97=EF=BC=8C?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=B1=E6=95=B0=E7=BB=84=E6=9E=84=E6=88=90?= =?UTF-8?q?=E7=9A=84=E5=8F=8C=E7=AB=AF=E9=98=9F=E5=88=97=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/queue/CircleQueue.java | 69 ++++++++++++++++++- .../basic/queue/CircleQueueTest.java | 13 +++- .../coding2017/basic/queue/Josephus.java | 14 ++-- .../basic/queue/QueueWithTwoStacks.java | 31 +++++---- .../basic/queue/QueueWithTwoStacksTest.java | 52 ++++++++++++++ .../jvm/loader/ByteCodeIterator.java | 2 +- 6 files changed, 161 insertions(+), 20 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java index 104ca0c92f..3434c87519 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java @@ -1,5 +1,72 @@ package com.github.miniyk2012.coding2017.basic.queue; -public class CircleQueue { +import java.util.ArrayDeque; +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int head = 0; + //队尾 + private int rear = 0; // rear指向的位置不放值,也就是说即使满了,也有一个空位 + + public CircleQueue(int capacity) { + elementData = new Object[capacity+1]; // 实际的数组长度要比容量大1 + } + + public CircleQueue() { + } + + public boolean isEmpty() { + return head == rear; + } + + public int size() { + + return Math.floorMod(rear-head, elementData.length); + } + + /** + * 如果满了还往里面放,则抛IndexOutOfBoundsException异常 + */ + public void enQueue(E data) { + if (isFull()) throw new IndexOutOfBoundsException("循环队列已满"); + elementData[rear] = data; + rear = Math.floorMod(rear+1, elementData.length); + } + + /** + * 如果为空,则抛IndexOutOfBoundsException异常 + * @return + */ + public E deQueue() { + if (isEmpty()) throw new IndexOutOfBoundsException("循环队列为空"); + E result = (E) elementData[head]; + head = Math.floorMod(head+1, elementData.length); + return result; + } + + public boolean isFull() { + return size() == elementData.length-1; + } + + public static void main(String[] args) { + /** + Math.floorMod( 2, 3) = 2 + Math.floorMod(-2, 3) = 1 + Math.floorMod( 2, -3) = -1 + Math.floorMod(-2, -3) = -2 + */ + System.out.println(Math.floorMod(1-2, 5)); + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java index a55219fde2..9d715a81a0 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java @@ -36,9 +36,20 @@ public void test() { Assert.assertEquals("a", queue.deQueue()); Assert.assertEquals("b", queue.deQueue()); Assert.assertEquals("c", queue.deQueue()); + + Assert.assertFalse(queue.isFull()); + Assert.assertEquals(2, queue.size()); + + queue.enQueue("f"); + queue.enQueue("g"); Assert.assertEquals("d", queue.deQueue()); Assert.assertEquals("e", queue.deQueue()); - + Assert.assertEquals("f", queue.deQueue()); + Assert.assertEquals("g", queue.deQueue()); + + Assert.assertEquals(0, queue.size()); + Assert.assertTrue(queue.isEmpty()); + Assert.assertFalse(queue.isFull()); } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java index 199a08628c..7c62997d2e 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java @@ -1,20 +1,24 @@ package com.github.miniyk2012.coding2017.basic.queue; -import java.util.ArrayList; import java.util.List; /** * 用Queue来实现Josephus问题 * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: - * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 知道最后一个人留下来 + * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 * @author liuxin * */ public class Josephus { - public static List execute(int n, int m){ - - return null; + public static List execute(int n, int m){ + CircleQueue circleQueue = new CircleQueue<>(n); + for (int i=0; i + */ public class QueueWithTwoStacks { - private Stack stack1; + private Stack stack1; private Stack stack2; @@ -12,29 +18,30 @@ public QueueWithTwoStacks() { stack2 = new Stack(); } - - - public boolean isEmpty() { - return false; + return stack1.isEmpty(); } - + private void move(Stack s1, Stack s2) { + while (!s1.empty()) { + s2.push(s1.pop()); + } + } public int size() { - return -1; + return stack1.size(); } - - public void enQueue(E item) { - + stack1.push(item); } public E deQueue() { - return null; + move(stack1, stack2); + E result = stack2.pop(); + move(stack2, stack1); + return result; } - } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..30c3268c5a --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,52 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +/** +* QueueWithTwoStacks Tester. +* +* @author +* @since
May 3, 2017
+* @version 1.0 +*/ +public class QueueWithTwoStacksTest { + QueueWithTwoStacks queue; + + @Before + public void before() throws Exception { + queue = new QueueWithTwoStacks<>(); + } + + @After + public void after() throws Exception { + } + + @Test + public void testFunction() { + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + queue.enQueue("d"); + Assert.assertEquals(4, queue.size()); + Assert.assertFalse(queue.isEmpty()); + + Assert.assertEquals("a", queue.deQueue()); + Assert.assertEquals("b", queue.deQueue()); + Assert.assertEquals("c", queue.deQueue()); + Assert.assertEquals(1, queue.size()); + Assert.assertFalse(queue.isEmpty()); + + queue.enQueue("e"); + Assert.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + Assert.assertTrue(queue.isEmpty()); + Assert.assertEquals(0, queue.size()); + + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java index 39500bb87c..1cd3b700aa 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java @@ -11,7 +11,7 @@ public class ByteCodeIterator { private int point = 0; public ByteCodeIterator(byte[] codes) { - this.codes = codes; + this.codes = codes.clone(); } public int nextU1toInt() { From 11baad280b46a4bd5eadb522e9dab9ca99b80270 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Wed, 3 May 2017 00:57:54 +0800 Subject: [PATCH 16/16] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=BA=A6=E7=91=9F?= =?UTF-8?q?=E5=A4=AB=E7=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/queue/CircleQueue.java | 6 +++--- .../coding2017/basic/queue/CircleQueueTest.java | 9 +++++++++ .../coding2017/basic/queue/Josephus.java | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java index 3434c87519..ff6f0f2699 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java @@ -3,7 +3,7 @@ import java.util.ArrayDeque; /** - * 用数组实现循环队列 + * 用数组实现循环队列,这也是一个队列,和普通队列有相同的外部特性,只是内部使用循环数组实现的罢了 * @author liuxin * * @param @@ -16,9 +16,9 @@ public class CircleQueue { private Object[] elementData = new Object[DEFAULT_SIZE] ; //队头 - private int head = 0; + protected int head = 0; //队尾 - private int rear = 0; // rear指向的位置不放值,也就是说即使满了,也有一个空位 + protected int rear = 0; // rear指向的位置不放值,也就是说即使满了,也有一个空位 public CircleQueue(int capacity) { elementData = new Object[capacity+1]; // 实际的数组长度要比容量大1 diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java index 9d715a81a0..1b4c4d1887 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java @@ -26,6 +26,8 @@ public void test() { queue.enQueue("a"); queue.enQueue("b"); queue.enQueue("c"); + // System.out.println(queue.head); + // System.out.println(queue.rear); queue.enQueue("d"); queue.enQueue("e"); @@ -42,14 +44,21 @@ public void test() { queue.enQueue("f"); queue.enQueue("g"); + // System.out.println(queue.head); + // System.out.println(queue.rear); Assert.assertEquals("d", queue.deQueue()); Assert.assertEquals("e", queue.deQueue()); + // System.out.println(queue.head); + // System.out.println(queue.rear); Assert.assertEquals("f", queue.deQueue()); Assert.assertEquals("g", queue.deQueue()); Assert.assertEquals(0, queue.size()); Assert.assertTrue(queue.isEmpty()); Assert.assertFalse(queue.isFull()); + + // System.out.println(queue.head); + // System.out.println(queue.rear); } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java index 7c62997d2e..9f70edd16d 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java @@ -1,5 +1,6 @@ package com.github.miniyk2012.coding2017.basic.queue; +import java.util.LinkedList; import java.util.List; /** @@ -14,10 +15,22 @@ public class Josephus { public static List execute(int n, int m){ CircleQueue circleQueue = new CircleQueue<>(n); + List result = new LinkedList<>(); for (int i=0; i