From 9512e534cb2eb05e0f86a0ee7e64ba2579e0e6e7 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 18 Apr 2017 15:35:34 +0800 Subject: [PATCH 1/5] update jvm --- .../coding2017/jvm/attr/CodeAttr.java | 15 +- .../coding2017/jvm/attr/LineNumberTable.java | 11 ++ .../jvm/attr/LocalVariableTable.java | 13 +- .../coding2017/jvm/clz/ClassFile.java | 15 +- .../coding2017/jvm/cmd/BiPushCmd.java | 23 ++++ .../coding2017/jvm/cmd/ByteCodeCommand.java | 128 +++++++++++++++++ .../coding2017/jvm/cmd/CommandParser.java | 85 ++++++++++++ .../coding2017/jvm/cmd/GetFieldCmd.java | 18 +++ .../coding2017/jvm/cmd/GetStaticFieldCmd.java | 24 ++++ .../coding2017/jvm/cmd/InvokeSpecialCmd.java | 23 ++++ .../coding2017/jvm/cmd/InvokeVirtualCmd.java | 21 +++ .../HarryHook/coding2017/jvm/cmd/LdcCmd.java | 29 ++++ .../coding2017/jvm/cmd/NewObjectCmd.java | 19 +++ .../coding2017/jvm/cmd/NoOperandCmd.java | 23 ++++ .../coding2017/jvm/cmd/OneOperandCmd.java | 27 ++++ .../coding2017/jvm/cmd/PutFieldCmd.java | 19 +++ .../coding2017/jvm/cmd/TwoOperandCmd.java | 67 +++++++++ .../coding2017/jvm/constant/ClassInfo.java | 4 + .../coding2017/jvm/constant/ConstantInfo.java | 15 +- .../coding2017/jvm/constant/FieldRefInfo.java | 5 + .../jvm/constant/MethodRefInfo.java | 5 + .../jvm/constant/NameAndTypeInfo.java | 6 + .../jvm/constant/NullConstantInfo.java | 5 + .../coding2017/jvm/constant/StringInfo.java | 6 + .../coding2017/jvm/constant/UTF8Info.java | 8 +- .../coding2017/jvm/method/Method.java | 4 + .../jvm/print/ClassFilePrinter.java | 51 +++++++ .../jvm/print/ConstantPoolPrinter.java | 25 ++++ .../jvm/test/ClassFileloaderTest.java | 81 ++++++++++- .../coding2017/stack/expr/InfixExpr.java | 77 +++++------ .../coding2017/stack/expr/InfixToPostfix.java | 12 ++ .../coding2017/stack/expr/PostfixExpr.java | 15 ++ .../stack/expr/PostfixExprTest.java | 37 +++++ .../coding2017/stack/expr/PrefixExpr.java | 129 ++++++++++++++++++ .../coding2017/stack/expr/PrefixExprTest.java | 43 ++++++ .../coding2017/stack/expr/Token.java | 50 +++++++ .../coding2017/stack/expr/TokenParser.java | 56 ++++++++ .../stack/expr/TokenParserTest.java | 39 ++++++ 38 files changed, 1176 insertions(+), 57 deletions(-) create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExprTest.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/Token.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java index 47a8bd2b1c..49a937c1b1 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java @@ -1,6 +1,7 @@ package com.github.HarryHook.coding2017.jvm.attr; import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.loader.ByteCodeIterator; import com.sun.org.apache.bcel.internal.generic.NEW; @@ -15,10 +16,10 @@ 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; @@ -30,7 +31,7 @@ public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int this.maxLocals = maxLocals; this.codeLen = codeLen; this.code = code; - // this.cmds = cmds; + this.cmds = cmds; } public void setLineNumberTable(LineNumberTable t) { @@ -92,9 +93,9 @@ public String toString(ConstantPool pool) { buffer.append("Code:").append(code).append("\n"); buffer.append("\n"); buffer.append(this.lineNumTable.toString()); - //buffer.append(this.localVarTable.toString(pool)); + buffer.append(this.localVarTable.toString(pool)); return buffer.toString(); } - + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LineNumberTable.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LineNumberTable.java index 51933e9bb6..c6b7d796b6 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LineNumberTable.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LineNumberTable.java @@ -53,5 +53,16 @@ public static LineNumberTable parse(ByteCodeIterator iter) { 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(); + +} } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LocalVariableTable.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LocalVariableTable.java index f9d5d0bdce..106ae86460 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LocalVariableTable.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/LocalVariableTable.java @@ -36,5 +36,16 @@ public static LocalVariableTable parse(ByteCodeIterator iter) { private void addLocalVariableItem(LocalVariableItem item) { this.items.add(item); } - + 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(); +} } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/clz/ClassFile.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/clz/ClassFile.java index 45e7464e9f..81856e9ad5 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/clz/ClassFile.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/clz/ClassFile.java @@ -18,7 +18,7 @@ public class ClassFile { private ClassIndex clzIndex; private ConstantPool pool; private List fields = new ArrayList(); - private List methods = new ArrayList();; + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -72,13 +72,13 @@ public void print() { } - private String getClassName() { + public String getClassName() { int thisClassIndex = clzIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } - private String getSuperClassName() { + public String getSuperClassName() { ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } @@ -98,6 +98,15 @@ public void addMethod(Method m) { public List getMethods() { return methods; } + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..6b1c020682 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..f5e6705a8a --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map 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); +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..5b78e0eeb1 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; + +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(); + } + + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..ec34e7b4a7 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,18 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.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/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..1090e17374 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,24 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..4afc337f47 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..6b494dceda --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,21 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.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); + } + + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..073ddd73a9 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.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; + + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..9c959e31dd --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.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/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..554eac0690 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.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/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..77bf40708b --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.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; + } + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..f3a197114c --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.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); + } + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..13edc86215 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; + +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/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java index 305ac57f5a..e4822e2bbb 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java @@ -25,4 +25,8 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java index 3d81ed1adb..6c502016a3 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java @@ -28,7 +28,16 @@ public ConstantInfo getConstantInfo(int index) { return this.constantPool.getConstantInfo(index); } - - - + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java index 6e8ddcb91b..d2d6a19f90 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java @@ -55,4 +55,9 @@ public String getFieldType() { NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java index 7815c8a6a2..a1055932a0 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java @@ -54,4 +54,9 @@ public String getParamAndReturnType() { return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java index 519656f681..29495489f4 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java @@ -45,4 +45,10 @@ public String getTypeInfo() { public String toString() { return "(" + getName() + "," + getTypeInfo() + ")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java index 59489a965c..b0f5ad9b80 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java @@ -11,4 +11,9 @@ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java index 1d625069be..442405aa36 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java @@ -24,4 +24,10 @@ public String toString() { return this.getConstantPool().getUTF8String(index); } + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java index 27c2ec9059..5c740bf402 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java @@ -29,8 +29,14 @@ public String toString() { public void setValue(String value) { this.value = value; } - public String getValue(){ + + public String getValue() { return value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java index d7dedc0439..1182364c71 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java @@ -2,6 +2,7 @@ package com.github.HarryHook.coding2017.jvm.method; import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; import javax.management.RuntimeErrorException; @@ -80,4 +81,7 @@ public String toString(ConstantPool pool) { buffer.append(desc); return buffer.toString(); } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); +} } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..6ede47692c --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java @@ -0,0 +1,51 @@ +package com.github.HarryHook.coding2017.jvm.print; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.HarryHook.coding2017.jvm.constant.StringInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; +import com.github.HarryHook.coding2017.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 = "F:\\Coding2017\\group02\\727171008\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.github.HarryHook.coding2017.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..3d6c791185 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,25 @@ +package com.github.HarryHook.coding2017.jvm.print; + +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.HarryHook.coding2017.jvm.constant.StringInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java index 524907ce9f..ee7e3b3092 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java @@ -9,6 +9,10 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.clz.ClassIndex; +import com.github.HarryHook.coding2017.jvm.cmd.BiPushCmd; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.cmd.OneOperandCmd; +import com.github.HarryHook.coding2017.jvm.cmd.TwoOperandCmd; import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; @@ -259,5 +263,80 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } - + /* + * 第四次测试 + */ + @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); + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java index 5b1dbd7fa4..a7b7ee00d2 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java @@ -13,73 +13,64 @@ public InfixExpr(String expr) { public float evaluate() { char[] ch = expr.toCharArray(); - MyStack stackOfTocken = new MyStack(); + MyStack stackOfOperator = new MyStack(); MyStack stackOfNumber = new MyStack(); for (int i = 0; i < ch.length; i++) { if (Character.isDigit(ch[i])) { - int tmp = Integer.parseInt("" + ch[i]); + float tmp = Float.parseFloat("" + ch[i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + tmp = tmp * 10 + Float.parseFloat("" + ch[i]); } stackOfNumber.push(tmp); } if (ch[i] == '+' || ch[i] == '-' || ch[i] == '*' || ch[i] == '/') { - stackOfTocken.push(ch[i]); + stackOfOperator.push(ch[i]); } - if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == '*') { - int tmp = Integer.parseInt("" + ch[++i]); + char operator = (char)stackOfOperator.peek(); + if (operator == '*' || operator == '/') { + float tmp = Float.parseFloat("" + ch[++i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + tmp = tmp * 10 + Float.parseFloat("" + ch[i]); } if (i != ch.length - 1) { i--; } stackOfNumber.push(tmp); - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 * tmp2); - stackOfTocken.pop(); - - } - if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == '/') { - int tmp = Integer.parseInt("" + ch[++i]); - while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); + float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); + if(operator == '*') { + stackOfNumber.push(tmp1 * tmp2); + } else { + stackOfNumber.push(tmp2 / tmp1); } - if (i != ch.length - 1) { - i--; - } - stackOfNumber.push(tmp); - - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp2 / tmp1); - stackOfTocken.pop(); + + stackOfOperator.pop(); } + } - // 将栈中的数字和运算法逆置,便于计算 + // 将栈中的数字和运算符逆置,从左往右结合 reverse(stackOfNumber); - reverse(stackOfTocken); - - while (!(stackOfTocken.isEmpty())) { - if ((char) stackOfTocken.peek() == '+') { - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 + tmp2); - } - - if ((char) stackOfTocken.peek() == '-') { - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 - tmp2); + reverse(stackOfOperator); + + while (!(stackOfOperator.isEmpty())) { + char operator = (char) stackOfOperator.peek(); + if (operator == '+' || operator == '-') { + float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); + float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); + if(operator == '+') { + stackOfNumber.push(tmp1 + tmp2); + } else { + stackOfNumber.push(tmp1 - tmp2); + } } - stackOfTocken.pop(); + + stackOfOperator.pop(); } return Float.parseFloat("" + stackOfNumber.pop()); @@ -104,4 +95,8 @@ private void reverse(MyStack s) { s.push(temp2); } + public static void main(String[] args) { + InfixExpr expr = new InfixExpr("2+3*4+5"); + System.out.println(expr.evaluate()); + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..57f6fa107b --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java @@ -0,0 +1,12 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..9fcee1a8f9 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java @@ -0,0 +1,15 @@ +package com.github.HarryHook.coding2017.stack.expr; + + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..7e78fa3997 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java @@ -0,0 +1,37 @@ +package com.github.HarryHook.coding2017.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); + } + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..97433b79a6 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java @@ -0,0 +1,129 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.lang.reflect.AnnotatedArrayType; +import java.util.ArrayList; + +import com.github.HarryHook.coding2017.basic.MyStack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + char[] ch = expr.toCharArray(); + MyStack stackOfOperator = new MyStack(); + MyStack stackOfNumber = new MyStack(); + ArrayList array = new ArrayList(); + for(int i=0; i 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + 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/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java new file mode 100644 index 0000000000..8d520fd68a --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java @@ -0,0 +1,56 @@ +package com.github.HarryHook.coding2017.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); + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..3067467a10 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.github.HarryHook.coding2017.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"); + + Assert.assertEquals(300, tokens.get(0).getIntValue()); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getIntValue()); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getIntValue()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getIntValue()); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getIntValue()); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getIntValue()); + } + +} \ No newline at end of file From e94ce7944ece1543abefad74499e5b57bb17928c Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 19 Apr 2017 14:15:22 +0800 Subject: [PATCH 2/5] add PrefixExpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 暂时想不到比这个更好的写法 --- group02/727171008/.classpath | 1 + .../coding2017/stack/expr/PrefixExpr.java | 133 +++++------------- 2 files changed, 33 insertions(+), 101 deletions(-) diff --git a/group02/727171008/.classpath b/group02/727171008/.classpath index 3e0fb272a8..429701a6eb 100644 --- a/group02/727171008/.classpath +++ b/group02/727171008/.classpath @@ -3,5 +3,6 @@ + diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java index 97433b79a6..bb9451c332 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java @@ -1,9 +1,7 @@ package com.github.HarryHook.coding2017.stack.expr; -import java.lang.reflect.AnnotatedArrayType; -import java.util.ArrayList; - -import com.github.HarryHook.coding2017.basic.MyStack; +import java.util.List; +import java.util.Stack; public class PrefixExpr { String expr = null; @@ -14,115 +12,48 @@ public PrefixExpr(String expr) { public float evaluate() { - char[] ch = expr.toCharArray(); - MyStack stackOfOperator = new MyStack(); - MyStack stackOfNumber = new MyStack(); - ArrayList array = new ArrayList(); - for(int i=0; i tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (Token token : tokens) { + exprStack.push(token); } - - for (int i = 0; i < array.size(); i++) { - - char operator = (char) array.get(i); - if (operator == '+'|| operator == '-' || operator == '*' || operator == '/') { - stackOfOperator.push(operator); + + while (!exprStack.isEmpty()) { + Token t = exprStack.pop(); + if (t.isNumber()) { + numStack.push(new Float(t.getIntValue())); } else { - stackOfNumber.push(array.get(i)); - } - - operator = (char)stackOfOperator.peek(); - //如果栈顶元素是'*','/'还需判断下个字符是不是'*','/' - if (!(stackOfOperator.isEmpty()) && operator == '*' || operator == '/') { - operator = (char) array.get(++i); - if(operator == '*') { - stackOfOperator.push(ch[i]); - } else { - i--; - } - if(operator == '/') { - stackOfOperator.push(ch[i]); - } else { - i--; - } - stackOfNumber.push(array.get(++i)); - stackOfNumber.push(array.get(++i)); - - float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); - float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); - - if((char)stackOfOperator.peek() == '*') { - stackOfNumber.push(tmp1 * tmp2); - } - if((char)stackOfOperator.peek() == '/'){ - stackOfNumber.push(tmp2 / tmp1); - } - - stackOfOperator.pop(); - } - - } - // 将栈中的数字和运算法逆置,从左往右结合 - reverse(stackOfNumber); - //reverse(stackOfOperator); + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(), f1, f2)); - while (!(stackOfOperator.isEmpty())) { - if ((char) stackOfOperator.peek() == '+') { - float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); - float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 + tmp2); - } - - if ((char) stackOfOperator.peek() == '-') { - float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); - float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 - tmp2); } - stackOfOperator.pop(); } - - return Float.parseFloat("" + stackOfNumber.pop()); + return numStack.pop().floatValue(); } - private void reverse(MyStack s) { - - if (s.isEmpty()) { - return; + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; } - // 如果s里面只有一个元素,就返回。具体实现是先pop出来一个,判断剩下的是不是空栈。 - Object tmp1 = s.pop(); - reverse(s); - if (s.isEmpty()) { - s.push(tmp1); - return; + if (op.equals("-")) { + return f1 - f2; } - Object temp2 = s.pop(); - reverse(s); - s.push(tmp1); - reverse(s); - s.push(temp2); - + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); } public static void main(String[] args) { - String expr = "-++6/*2 9 3 * 4 2 8"; - PrefixExpr prefixExpr = new PrefixExpr(expr); + + PrefixExpr prefixExpr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); System.out.println(prefixExpr.evaluate()); } From 1208fb8d26f9d8fd97272faf3834e30926a6b91a Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 24 Apr 2017 11:23:13 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E6=B1=82?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前中后序表达式求值,以及中序表达式转后序表达式 --- .../coding2017/stack/expr/InfixExpr.java | 19 ++++---- .../coding2017/stack/expr/InfixToPostfix.java | 45 ++++++++++++++++++- .../coding2017/stack/expr/PostfixExpr.java | 43 +++++++++++++++++- .../coding2017/stack/expr/PrefixExpr.java | 10 ++--- 4 files changed, 98 insertions(+), 19 deletions(-) diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java index a7b7ee00d2..b9667fdaac 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java @@ -23,7 +23,7 @@ public float evaluate() { while (i < ch.length - 1 && Character.isDigit(ch[++i])) { tmp = tmp * 10 + Float.parseFloat("" + ch[i]); } - + stackOfNumber.push(tmp); } @@ -31,7 +31,7 @@ public float evaluate() { stackOfOperator.push(ch[i]); } - char operator = (char)stackOfOperator.peek(); + char operator = (char) stackOfOperator.peek(); if (operator == '*' || operator == '/') { float tmp = Float.parseFloat("" + ch[++i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { @@ -44,15 +44,15 @@ public float evaluate() { float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); - if(operator == '*') { + if (operator == '*') { stackOfNumber.push(tmp1 * tmp2); - } else { - stackOfNumber.push(tmp2 / tmp1); + } else { + stackOfNumber.push(tmp2 / tmp1); } - + stackOfOperator.pop(); } - + } // 将栈中的数字和运算符逆置,从左往右结合 reverse(stackOfNumber); @@ -63,10 +63,10 @@ public float evaluate() { if (operator == '+' || operator == '-') { float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); - if(operator == '+') { + if (operator == '+') { stackOfNumber.push(tmp1 + tmp2); } else { - stackOfNumber.push(tmp1 - tmp2); + stackOfNumber.push(tmp1 - tmp2); } } @@ -95,6 +95,7 @@ private void reverse(MyStack s) { s.push(temp2); } + public static void main(String[] args) { InfixExpr expr = new InfixExpr("2+3*4+5"); System.out.println(expr.evaluate()); diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java index 57f6fa107b..10088e28cd 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java @@ -1,12 +1,53 @@ package com.github.HarryHook.coding2017.stack.expr; +import java.util.ArrayList; import java.util.List; +import java.util.Stack; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array; + +//中序表达式: 3*20+12*5-40/2 转换成后续表达式:3 20 * 12 5 * + 40 2 / - +//思路:当前token依次从左往右读取, 数字依次append, 当前入栈的运算符的优先级小于等于栈顶的运算符,栈顶操作符出栈 public class InfixToPostfix { - public static List convert(String expr) { + public List convert(String expr) { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + List listOfTokens = new ArrayList<>(); + + Stack opsStack = new Stack<>(); + + for (Token token : tokens) { + + if (token.isNumber()) { + listOfTokens.add(token); + } else if (token.isOperator()) { // 还需判断当前操作符和栈顶操作符的优先级 + if (opsStack.isEmpty()) { + opsStack.push(token); + } else { + if (!token.hasHigherPriority(opsStack.peek())) { + listOfTokens.add(opsStack.pop()); + } + opsStack.push(token); + } + + } + } + while (!(opsStack.isEmpty())) { // exprStack 为空,但操作符栈还有元素 + listOfTokens.add(opsStack.pop()); + } + return listOfTokens; + } - return null; + public static void main(String[] args) { + InfixToPostfix toPostfix = new InfixToPostfix(); + List t = new ArrayList(); + String expr = "3+20+12*5+40/2"; + t = toPostfix.convert(expr); + System.out.println("expr: " + expr); + System.out.println("PostfixExpr: " + t); } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java index 9fcee1a8f9..49bebad1a7 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java @@ -1,5 +1,7 @@ package com.github.HarryHook.coding2017.stack.expr; +import java.util.List; +import java.util.Stack; public class PostfixExpr { String expr = null; @@ -7,9 +9,46 @@ public class PostfixExpr { public PostfixExpr(String expr) { this.expr = expr; } - + public float evaluate() { - return 0.0f; + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack numStack = new Stack<>(); + for (Token token : tokens) { + + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + // 注意,此时计算的顺序和前序的次序相反 + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + + public static void main(String[] args) { + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + System.out.println("The result of the expression: " + expr.evaluate()); } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java index bb9451c332..d93b6e32fe 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java @@ -20,16 +20,15 @@ public float evaluate() { for (Token token : tokens) { exprStack.push(token); } - + System.out.println(tokens); while (!exprStack.isEmpty()) { Token t = exprStack.pop(); if (t.isNumber()) { numStack.push(new Float(t.getIntValue())); - } else { + } else if(t.isOperator()){ Float f1 = numStack.pop(); Float f2 = numStack.pop(); numStack.push(calculate(t.toString(), f1, f2)); - } } return numStack.pop().floatValue(); @@ -52,9 +51,8 @@ private Float calculate(String op, Float f1, Float f2) { } public static void main(String[] args) { - - PrefixExpr prefixExpr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); - System.out.println(prefixExpr.evaluate()); + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + System.out.println("The result of the expression: " + expr.evaluate()); } } \ No newline at end of file From d0aed3355041dee99f16cdb452333ddb163e4244 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 24 Apr 2017 11:24:22 +0800 Subject: [PATCH 4/5] add jvm_4 --- .../coding2017/jvm/attr/CodeAttr.java | 56 +++-- .../coding2017/jvm/attr/LineNumberTable.java | 19 +- .../coding2017/jvm/clz/ClassFile.java | 45 ++-- .../coding2017/jvm/cmd/CommandParser.java | 198 ++++++++++++------ .../coding2017/jvm/constant/ConstantPool.java | 2 +- .../coding2017/jvm/method/Method.java | 4 +- .../coding2017/queue/CircleQueue.java | 38 ++++ 7 files changed, 251 insertions(+), 111 deletions(-) create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java index 49a937c1b1..9ecd803572 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java @@ -2,6 +2,7 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.cmd.CommandParser; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.loader.ByteCodeIterator; import com.sun.org.apache.bcel.internal.generic.NEW; @@ -16,16 +17,18 @@ 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; @@ -43,40 +46,44 @@ public void setLocalVariableTable(LocalVariableTable 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); - - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); - + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, cmds); + int exceptionLength = iter.nextU2ToInt(); - if(exceptionLength > 0) { + if (exceptionLength > 0) { String exceptionTable = iter.nextUxToHexString(exceptionLength); System.out.println("exception Table has not complemented" + exceptionTable); } - //解析子属性 + // 解析子属性 int subAttrCount = iter.nextU2ToInt(); - - for(int j=1; j<=subAttrCount; j++) { - + + for (int j = 1; j <= subAttrCount; j++) { + int subAttrIndex = iter.nextU2ToInt(); String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); iter.back(2); - - if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { LineNumberTable t = LineNumberTable.parse(iter); codeAttr.setLineNumberTable(t); - - } else if(AttributeInfo.LOCAL_VAR_TABLE.equals(subAttrName)) { + + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(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 implement" + subAttrName); } @@ -88,14 +95,17 @@ private void setStackMapTable(StackMapTable t) { this.stackMapTable = t; } + public String toString(ConstantPool pool) { StringBuffer buffer = new StringBuffer(); - buffer.append("Code:").append(code).append("\n"); + for(int i=0;i fields = new ArrayList(); - private List methods = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; } + public void setClzIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } + public AccessFlag getAccessFlag() { return accessFlag; } @@ -82,31 +83,51 @@ public String getSuperClassName() { ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } - + public void addField(Field f) { fields.add(f); } - + public List getFields() { return fields; } - + public void addMethod(Method m) { methods.add(m); - + } + public List getMethods() { return methods; } - public Method getMethod(String methodName, String paramAndReturnType){ - - + + public Method getMethod(String methodName, String paramAndReturnType) { + + for (Method m : methods) { + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + if (name.equals(methodName) && desc.equals(paramAndReturnType)) { + return m; + } + } return null; } - public Method getMainMethod(){ - + + public Method getMainMethod() { + for (Method m : methods) { + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if (name.equals("main") && desc.equals("([Ljava/lang/String;)V")) { + return m; + } + } return null; } - } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java index 5b78e0eeb1..b982fa7aa4 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java @@ -6,80 +6,150 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; 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; + + 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) { + + if ((codes == null) || (codes.length() == 0) || (codes.length() % 2) != 0) { + throw new RuntimeException("the orignal code is not correct"); + + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + // System.out.println( cmd.toString(clzFile.getConstPool())); + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); + } + } - private static void calcuateOffset(List cmds) { + calcuateOffset(cmds); - int offset = 0; - for (ByteCodeCommand cmd : cmds) { - cmd.setOffset(offset); - offset += cmd.getLength(); - } + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; + } + 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; - } + private static class CommandIterator { + String codes = null; + int pos = 0; - public boolean hasNext() { - return pos < this.codes.length(); - } + CommandIterator(String codes) { + this.codes = codes; + } - public String next2CharAsString() { - String result = codes.substring(pos, pos + 2); - pos += 2; - return result; - } + public boolean hasNext() { + return pos < this.codes.length(); + } - public int next2CharAsInt() { - String s = this.next2CharAsString(); - return Integer.valueOf(s, 16).intValue(); - } + 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(); } + + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java index 9d06349f3b..92d1b381d1 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java @@ -25,7 +25,7 @@ public String getUTF8String(int index) { return ((UTF8Info) this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() - 1; } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java index 1182364c71..08b8ff029b 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java @@ -77,8 +77,8 @@ public String toString(ConstantPool pool) { StringBuffer buffer = new StringBuffer(); String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); - buffer.append(name); - buffer.append(desc); + buffer.append(name).append(":").append(desc).append("\n"); + buffer.append(this.codeAttr.toString(pool)); return buffer.toString(); } public ByteCodeCommand[] getCmds() { diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java new file mode 100644 index 0000000000..cd82fb2550 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java @@ -0,0 +1,38 @@ +package com.github.HarryHook.coding2017.queue; + +/** + * 用数组实现循环队列 + * + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + return false; + + } + + public int size() { + return -1; + } + + public void enQueue(E data) { + + } + + public E deQueue() { + return null; + } +} From 18f0c6c1058c7a859f9dd2f7be2f7110af5da041 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 24 Apr 2017 11:35:34 +0800 Subject: [PATCH 5/5] add queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现循环队列,约瑟夫环以及双栈实现队列 --- .../HarryHook/coding2017/queue/Josephus.java | 18 ++++++ .../coding2017/queue/JosephusTest.java | 25 +++++++++ .../HarryHook/coding2017/queue/Queue.java | 55 +++++++++++++++++++ .../coding2017/queue/QueueWithTwoStacks.java | 37 +++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java new file mode 100644 index 0000000000..7b5fe53f5e --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java @@ -0,0 +1,18 @@ +package com.github.HarryHook.coding2017.queue; + +import java.util.List; + +/** + * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 + * + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m) { + return null; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java new file mode 100644 index 0000000000..39d2ef9971 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java @@ -0,0 +1,25 @@ +package com.github.HarryHook.coding2017.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/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java new file mode 100644 index 0000000000..3be0147770 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java @@ -0,0 +1,55 @@ +package com.github.HarryHook.coding2017.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/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c72abadcd2 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java @@ -0,0 +1,37 @@ +package com.github.HarryHook.coding2017.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * + * @author liuxin + * + * @param + */ +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; + } + +}