From 0e158b1cccd7e2f46d20c633ed687455c3e1b45c Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Sat, 1 Apr 2017 09:42:36 +0800 Subject: [PATCH 001/151] update .gitignore file --- group17/82427129/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/group17/82427129/.gitignore b/group17/82427129/.gitignore index 090f729088..35cadcc5f6 100644 --- a/group17/82427129/.gitignore +++ b/group17/82427129/.gitignore @@ -14,4 +14,6 @@ .project -Test.java \ No newline at end of file +Test.java + +Algorithms/ \ No newline at end of file From 2beb5229e0943c8f49bf49036636d89e8293d7b7 Mon Sep 17 00:00:00 2001 From: Ren650119726 <102228177@qq.com> Date: Sun, 9 Apr 2017 22:54:02 +0800 Subject: [PATCH 002/151] =?UTF-8?q?=E7=AC=AC=E4=BA=94=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/102228177/work2_26/.classpath | 16 +- .../src/com/coderising/array/ArrayUtil.java | 19 +- .../jvm/loader/ClassFileLoader.java | 81 +++++++ .../jvm/test/ClassFileloaderTest.java | 93 ++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 28 +++ .../coding/basic/linklist/LRUPageFrame.java | 150 +++++++++++++ .../basic/linklist/LRUPageFrameTest.java | 31 +++ .../src/com/coderising/data/LinkedList.java | 42 ++-- .../com/coderising/data/LinkedListTest.java | 7 +- .../coderising/download/DownloadThread.java | 2 +- .../coderising/download/FileDownloader.java | 2 +- .../download/FileDownloaderTest.java | 5 +- .../download/impl/ConnectionImpl.java | 2 +- .../download/impl/ConnectionManagerImpl.java | 2 +- .../com/coderising/jvm/clz/AccessFlag.java | 25 +++ .../src/com/coderising/jvm/clz/ClassFile.java | 75 +++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 ++ .../coderising/jvm/constant/ClassInfo.java | 33 +++ .../coderising/jvm/constant/ConstantInfo.java | 38 ++++ .../coderising/jvm/constant/ConstantPool.java | 39 ++++ .../coderising/jvm/constant/FieldRefInfo.java | 54 +++++ .../jvm/constant/MethodRefInfo.java | 55 +++++ .../jvm/constant/NameAndTypeInfo.java | 45 ++++ .../jvm/constant/NullConstantInfo.java | 13 ++ .../coderising/jvm/constant/StringInfo.java | 26 +++ .../com/coderising/jvm/constant/UTF8Info.java | 32 +++ .../jvm/loader/ByteCodeIterator.java | 49 +++++ .../jvm/loader/ClassFileLoader.java | 137 ++++++++++++ .../jvm/loader/ClassFileParser.java | 115 ++++++++++ .../jvm/test/ClassFileloaderTest.java | 203 ++++++++++++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 28 +++ .../src/com/coderising/jvm/util/Util.java | 24 +++ .../src/com/coding/basic/stack/ArrayList.java | 150 +++++++++++++ .../src/com/coding/basic/stack/Iterator.java | 8 + .../src/com/coding/basic/stack/List.java | 10 + .../src/com/coding/basic/stack/Stack.java | 22 ++ .../src/com/coding/basic/stack/StackUtil.java | 45 ++++ 37 files changed, 1673 insertions(+), 52 deletions(-) create mode 100644 group17/102228177/work3_26/src/com/coderising/jvm/loader/ClassFileLoader.java create mode 100644 group17/102228177/work3_26/src/com/coderising/jvm/test/ClassFileloaderTest.java create mode 100644 group17/102228177/work3_26/src/com/coderising/jvm/test/EmployeeV1.java create mode 100644 group17/102228177/work3_26/src/com/coding/basic/linklist/LRUPageFrame.java create mode 100644 group17/102228177/work3_26/src/com/coding/basic/linklist/LRUPageFrameTest.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/clz/AccessFlag.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/clz/ClassFile.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/clz/ClassIndex.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/ClassInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/ConstantPool.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/MethodRefInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/NullConstantInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/StringInfo.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/constant/UTF8Info.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/loader/ClassFileLoader.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/test/ClassFileloaderTest.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/test/EmployeeV1.java create mode 100644 group17/102228177/work4_09/src/com/coderising/jvm/util/Util.java create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/ArrayList.java create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/Iterator.java create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/List.java create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java diff --git a/group17/102228177/work2_26/.classpath b/group17/102228177/work2_26/.classpath index 80437ca942..dfa83d7793 100644 --- a/group17/102228177/work2_26/.classpath +++ b/group17/102228177/work2_26/.classpath @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/group17/102228177/work2_26/src/com/coderising/array/ArrayUtil.java b/group17/102228177/work2_26/src/com/coderising/array/ArrayUtil.java index 60949d043e..a0dc5262db 100644 --- a/group17/102228177/work2_26/src/com/coderising/array/ArrayUtil.java +++ b/group17/102228177/work2_26/src/com/coderising/array/ArrayUtil.java @@ -34,7 +34,7 @@ public static void main(String[] args) { // System.out.println(Arrays.toString(util.merge(a1, a2))); System.out.println(Arrays.toString(util.fibonacci(15))); - System.out.println(Arrays.toString(util.getPrimes(23))); +// System.out.println(Arrays.toString(util.getPrimes(23))); } /** @@ -115,14 +115,15 @@ public int[] grow(int [] oldArray, int size){ */ public int[] fibonacci(int max){ List list = new ArrayList(); - int f1 = 1, f2 = 1, f = 0; - list.add(f1); - list.add(f2); - while(f < max){ - f = f1+f2; - f1 = f2; - f2 = f; - list.add(f); + if (max <= 1) { + return new int[]{}; + } + int lo = 0; + int hi = 1; + while(hi clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + String name = ""; + for (int i = 0; i < className.length(); i++) { + if(className.charAt(i)=='.'){ + name += File.separatorChar; + }else{ + name += className.charAt(i); + } + } + File file = new File(getClassPath()+ File.separatorChar +name+".class"); + InputStream in = null; + ByteArrayOutputStream out = null; + try { + in = new FileInputStream(file); + out = new ByteArrayOutputStream(); + byte[] buff = new byte[1024*2]; + int len = 0; + while((len=in.read(buff))!=-1){ + out.write(buff, 0, len); + } + return out.toByteArray(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + finally { + if(in!=null){ + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(out!=null){ + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return null; + + + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuilder sb = new StringBuilder(); + for (String string : clzPaths) { + sb.append(string).append(";"); + } + sb = sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } +} \ No newline at end of file diff --git a/group17/102228177/work3_26/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group17/102228177/work3_26/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..1e51c27361 --- /dev/null +++ b/group17/102228177/work3_26/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,93 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.loader.ClassFileLoader; + + + + + +public class ClassFileloaderTest { + + +// static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path1 = "D:\\git\\coding2017\\group17\\102228177\\work3_26\\bin"; + static String path2 = "C:\temp"; + + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i= capacity) { + removeLast(); + } + addNewNodetoHead(node); + } + } + + private void addNewNodetoHead(Node node) { + + if(isEmpty()){ + + node.prev = null; + node.next = null; + first = node; + last = node; + + } else{ + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + this.currentSize ++; + } + + private Node find(int data){ + + Node node = first; + while(node != null){ + if(node.pageNum == data){ + return node; + } + node = node.next; + } + return null; + + } + + + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize --; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + * + * @param node + */ + private void moveExistingNodeToHead(Node node) { + + if (node == first) { + + return; + } + else if(node == last){ + //当前节点是链表尾, 需要放到链表头 + Node prevNode = node.prev; + prevNode.next = null; + last.prev = null; + last = prevNode; + + } else{ + //node 在链表的中间, 把node 的前后节点连接起来 + Node prevNode = node.prev; + prevNode.next = node.next; + + Node nextNode = node.next; + nextNode.prev = prevNode; + + + } + + node.prev = null; + node.next = first; + first.prev = node; + first = node; + + } + private boolean isEmpty(){ + return (first == null) && (last == null); + } + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + Node node = first; + while(node != null){ + buffer.append(node.pageNum); + + node = node.next; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } +} \ No newline at end of file diff --git a/group17/102228177/work3_26/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group17/102228177/work3_26/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..c323d03b3f --- /dev/null +++ b/group17/102228177/work3_26/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + } + +} \ No newline at end of file diff --git a/group17/102228177/work3_5/src/com/coderising/data/LinkedList.java b/group17/102228177/work3_5/src/com/coderising/data/LinkedList.java index 22a72affaf..ee2a7fd554 100644 --- a/group17/102228177/work3_5/src/com/coderising/data/LinkedList.java +++ b/group17/102228177/work3_5/src/com/coderising/data/LinkedList.java @@ -292,22 +292,19 @@ public void removeRange(int min, int max){ throw new RuntimeException("LinkedList is empty!"); }else{ Node q = head; - //头判断 - if((int)q.data>min && (int)q.datamin && (int)p.data constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/FieldRefInfo.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/MethodRefInfo.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/NullConstantInfo.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/StringInfo.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/constant/UTF8Info.java b/group17/102228177/work4_09/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/102228177/work4_09/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..8334e80b63 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,49 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/loader/ClassFileLoader.java b/group17/102228177/work4_09/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..81264ceed7 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,137 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + /*private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + }*/ + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + /*public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } +*/ + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + + +} diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/test/EmployeeV1.java b/group17/102228177/work4_09/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group17/102228177/work4_09/src/com/coderising/jvm/util/Util.java b/group17/102228177/work4_09/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group17/102228177/work4_09/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i= maxLen){ + grow(); + } + elements[size] = o; + size++; + } + + /** + * 数组扩容 + */ + private void grow(){ + maxLen = maxLen + (maxLen >> 1); + Object[] newArr = new Object[maxLen]; + System.arraycopy(elements, 0, newArr, 0, size); + elements = newArr; + } + + /** + * 在指定索引处添加元素 + * @param i 指定索引 + * @param o 添加元素 + */ + public void add(int i,Object o){ + //判断插入位置大于数组实际长度 + if(i > size){ + size = i; + if(size >= maxLen){//数组大小大于数组最大容量则需要扩容 + grow(); + } + } + //插入位置不大于数组实际长度时,将插入位置的元素向后移。 + for (int j = size; j > i ; j++) { + elements[j] = elements[j-1]; + } + elements[i] = o; + size++; + } + + /** + * 获取传入索引的元素 + * @param index 索引 + * @return 返回传入索引的元素 + */ + public Object get(int index){ + //索引不在实际范围内 + if(index < 0||index >= size){ + throw new ArrayIndexOutOfBoundsException(); + } + for (int i = 0; i < size; i++) { + return elements[index]; + } + return null; + } + + /** + * 删除指定索引元素并返回 + * @param index + * @return 该索引处元素 + */ + public Object remove(int index){ + //索引不在实际范围内 + if(index < 0||index >= size){ + throw new ArrayIndexOutOfBoundsException(); + }else{ + for (int j = index; j < size-1; j++) { + elements[j]=elements[j+1]; + } + size--; + return elements[index]; + } + } + + /** + * 获取大小 + * @return + */ + public int size(){ + return size; + } + + public Iterator iterator(){ + return new ArrayListIterator(); + } + + private class ArrayListIterator implements Iterator{ + int cursor; + + @Override + public boolean hasNext() { + return cursor != size; + } + + @Override + public Object next() { + int i = cursor; + if(i >= size){ + throw new NoSuchElementException(); + } + if (i >= elements.length){ + throw new ConcurrentModificationException(); + } + cursor = i+1; + return elements[i]; + } + } + + public static void main(String[] args) { + ArrayList list = new ArrayList(); + list.add(0); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(6, 6); + list.remove(3); + for (int i = 0; i < list.size(); i++) { + System.out.println(i+":"+list.get(i)); + } + + Iterator it = list.iterator(); + while (it.hasNext()) { + System.out.println(it.next()); + } + } +} diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/Iterator.java b/group17/102228177/work4_09/src/com/coding/basic/stack/Iterator.java new file mode 100644 index 0000000000..f51a971a1c --- /dev/null +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/Iterator.java @@ -0,0 +1,8 @@ +package com.coding.basic.stack; + +public interface Iterator { + + public boolean hasNext(); + public Object next(); + +} \ No newline at end of file diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/List.java b/group17/102228177/work4_09/src/com/coding/basic/stack/List.java new file mode 100644 index 0000000000..2d2c693e0d --- /dev/null +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/List.java @@ -0,0 +1,10 @@ +package com.coding.basic.stack; + +public interface List { + + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} \ No newline at end of file diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java b/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..1af8fbfb7a --- /dev/null +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,22 @@ +package com.coding.basic.stack; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + } + + public Object pop(){ + return null; + } + + public Object peek(){ + return null; + } + public boolean isEmpty(){ + return false; + } + public int size(){ + return -1; + } +} \ No newline at end of file diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..2ecca1811c --- /dev/null +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + return null; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + return false; + } + + +} \ No newline at end of file From fe754de1bc1ddbaccb4b29010da90075fea42f15 Mon Sep 17 00:00:00 2001 From: earliest Date: Sun, 9 Apr 2017 22:51:08 -0700 Subject: [PATCH 003/151] jvm constant pool assignemnt --- .../jvm/loader/ClassFileLoader.java | 20 +- .../jvm/test/ClassFileloaderTest.java | 308 ++++++++++++------ group17/article/20170402-20170409.md | 2 +- 3 files changed, 223 insertions(+), 107 deletions(-) mode change 100644 => 100755 group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest.java diff --git a/group17/1282579502/src/com/coderising/jvm/loader/ClassFileLoader.java b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileLoader.java index 6d669e294f..ec9ea83caf 100644 --- a/group17/1282579502/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -9,18 +9,24 @@ import java.util.Collection; import java.util.List; +import com.coderising.jvm.clz.ClassFile; + public class ClassFileLoader { private List clzPaths = new ArrayList(); + public ClassFileLoader(){ + + } + public byte[] readBinaryCode(String className) { String classPath = convertToFilePath(className); File targetFile = null; for(int i = 0; i< clzPaths.size(); i++){ String fullPath = clzPaths.get(i)+File.separator+classPath; - System.out.println("path: " + fullPath); + //System.out.println("path: " + fullPath); File temp = new File(fullPath); if(temp.exists()) { targetFile = temp; @@ -29,10 +35,10 @@ public byte[] readBinaryCode(String className) { } if(targetFile != null){ - System.out.println("targetFile: " + targetFile.getAbsolutePath()); + //System.out.println("targetFile: " + targetFile.getAbsolutePath()); } long fileLength = targetFile.length(); - System.out.println("File length: " + fileLength); + //System.out.println("File length: " + fileLength); byte[] byteArray = new byte[(int)fileLength]; FileInputStream is = null; try { @@ -61,6 +67,14 @@ public byte[] readBinaryCode(String className) { } + public ClassFile loadClass(String className){ + byte[] ba = readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(ba); + } + + + private String convertToFilePath(String className){ return className.replaceAll("\\.", File.separator) + ".class"; } diff --git a/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest.java old mode 100644 new mode 100755 index 4df3f4b529..d3e036dee0 --- a/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,103 +1,205 @@ -package com.coderising.jvm.test; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coderising.jvm.loader.ClassFileLoader; - - - - - -public class ClassFileloaderTest { - - - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; - static String path2 = "C:\temp"; - static String path3 = "/Users/erlisuo/Documents/workspace/codeRising2017working/1282579502/bin"; - - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testClassPath(){ - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - loader.addClassPath(path2); - - String clzPath = loader.getClassPath(); - - Assert.assertEquals(path1+";"+path2,clzPath); - - } - - @Test - public void testClassFileLength() { - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - loader.addClassPath(path2); - loader.addClassPath(path3); - String className = "com.coderising.jvm.test.EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1056, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - loader.addClassPath(path3); - String className = "com.coderising.jvm.test.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; - - - String acctualValue = this.byteToHexString(codes); - - Assert.assertEquals("cafebabe", acctualValue); - } - - - @Test - public void testToHexString(){ - byte b1 = 'a'; - byte b2 = 'b'; - System.out.println("Binary: " + Integer.toBinaryString(b1) + " decimal: " + Integer.toString(b1) + " hex: " + Integer.toHexString(b1)); - System.out.println("Binary: " + Integer.toBinaryString(b2) + " decimal: " + Integer.toString(b2) + " hex: " + Integer.toHexString(b2)); - - byte[] bArray = new byte[]{b1, b2}; - System.out.println(byteToHexString(bArray)); - } - - - - private String byteToHexString(byte[] codes ){ - StringBuffer buffer = new StringBuffer(); - for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + + +} diff --git a/group17/article/20170402-20170409.md b/group17/article/20170402-20170409.md index 3d45ad0516..f0d32f145f 100644 --- a/group17/article/20170402-20170409.md +++ b/group17/article/20170402-20170409.md @@ -30,7 +30,7 @@ 516886559 -1282579502 +1282579502 https://www.evernote.com/l/AZ3ajLOAlTVHw7foK2KLb-bWZ7kw6FjljDA 614982500 From 83bb942114853f18699d0d5e2b33e82e824c6b3f Mon Sep 17 00:00:00 2001 From: earliest Date: Sun, 9 Apr 2017 22:53:56 -0700 Subject: [PATCH 004/151] jvm constant pool assignment --- .../com/coderising/jvm/clz/AccessFlag.java | 25 ++++ .../src/com/coderising/jvm/clz/ClassFile.java | 75 ++++++++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 +++ .../coderising/jvm/constant/ClassInfo.java | 24 ++++ .../coderising/jvm/constant/ConstantInfo.java | 30 +++++ .../jvm/constant/ConstantInfoFactory.java | 93 +++++++++++++++ .../coderising/jvm/constant/ConstantPool.java | 29 +++++ .../coderising/jvm/constant/FieldRefInfo.java | 54 +++++++++ .../coderising/jvm/constant/FloatRefInfo.java | 15 +++ .../coderising/jvm/constant/IntegerInfo.java | 22 ++++ .../InvalidConstantInfoTypeException.java | 11 ++ .../jvm/constant/MethodRefInfo.java | 55 +++++++++ .../jvm/constant/NameAndTypeInfo.java | 45 ++++++++ .../jvm/constant/NullConstantInfo.java | 13 +++ .../coderising/jvm/constant/StringInfo.java | 26 +++++ .../com/coderising/jvm/constant/UTF8Info.java | 32 +++++ .../jvm/loader/ByteCodeIterator.java | 63 ++++++++++ .../jvm/loader/ClassFileParser.java | 96 +++++++++++++++ .../jvm/test/ByteCodeIteratorTest.java | 51 ++++++++ .../src/com/coderising/jvm/util/Util.java | 24 ++++ .../src/com/coding/basic/stack/Stack.java | 24 ++++ .../src/com/coding/basic/stack/StackUtil.java | 109 ++++++++++++++++++ 22 files changed, 935 insertions(+) create mode 100755 group17/1282579502/src/com/coderising/jvm/clz/AccessFlag.java create mode 100755 group17/1282579502/src/com/coderising/jvm/clz/ClassFile.java create mode 100755 group17/1282579502/src/com/coderising/jvm/clz/ClassIndex.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/ClassInfo.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group17/1282579502/src/com/coderising/jvm/constant/FloatRefInfo.java create mode 100644 group17/1282579502/src/com/coderising/jvm/constant/IntegerInfo.java create mode 100644 group17/1282579502/src/com/coderising/jvm/constant/InvalidConstantInfoTypeException.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/MethodRefInfo.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/NullConstantInfo.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/StringInfo.java create mode 100755 group17/1282579502/src/com/coderising/jvm/constant/UTF8Info.java create mode 100755 group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100755 group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group17/1282579502/src/com/coderising/jvm/test/ByteCodeIteratorTest.java create mode 100755 group17/1282579502/src/com/coderising/jvm/util/Util.java create mode 100755 group17/1282579502/src/com/coding/basic/stack/Stack.java create mode 100755 group17/1282579502/src/com/coding/basic/stack/StackUtil.java diff --git a/group17/1282579502/src/com/coderising/jvm/clz/AccessFlag.java b/group17/1282579502/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100755 index 0000000000..aab65b780b --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ + package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group17/1282579502/src/com/coderising/jvm/clz/ClassFile.java b/group17/1282579502/src/com/coderising/jvm/clz/ClassFile.java new file mode 100755 index 0000000000..650ca8375d --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + 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()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/clz/ClassIndex.java b/group17/1282579502/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100755 index 0000000000..e424f284b3 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ClassInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100755 index 0000000000..aea9048ea4 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100755 index 0000000000..b99ed30fbf --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int INTEGER_INFO = 3; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java new file mode 100644 index 0000000000..01df38c682 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java @@ -0,0 +1,93 @@ +package com.coderising.jvm.constant; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.loader.ByteCodeIterator; +import com.coderising.jvm.util.Util; + +public class ConstantInfoFactory { + public ByteCodeIterator iter = null; + public ConstantPool pool = null; + public ConstantInfoFactory(ByteCodeIterator iter, ConstantPool pool){ + this.iter = iter; + this.pool = pool; + } + + public void fillNextConstantInfo() throws InvalidConstantInfoTypeException, UnsupportedEncodingException{ + int constantIdentifier = iter.getNextByte(); + ConstantInfo var = null; + System.out.println("constant identifyer: " + constantIdentifier); + var = classify(constantIdentifier); + pool.addConstantInfo(var); + } + + public ConstantInfo classify(int constantInfoTypeId) throws InvalidConstantInfoTypeException, UnsupportedEncodingException{ + ConstantInfo ret = null; + switch(constantInfoTypeId){ + case ConstantInfo.CLASS_INFO: + ClassInfo classInfo = new ClassInfo(pool); + byte[] utf8Index = iter.getNextNBytes(2); + System.out.println("constant classInfo: utf index: " + Util.byteToInt(utf8Index)); + classInfo.setUtf8Index(Util.byteToInt(utf8Index)); + ret = classInfo; + + break; + case ConstantInfo.FIELD_INFO: + FieldRefInfo fieldInfo = new FieldRefInfo(pool); + int classInfoIndex = Util.byteToInt(iter.getNextNBytes(2)); + fieldInfo.setClassInfoIndex(classInfoIndex); + int nameAndTypeIndex = Util.byteToInt(iter.getNextNBytes(2)); + fieldInfo.setNameAndTypeIndex(nameAndTypeIndex); + ret = fieldInfo; + break; + case ConstantInfo.INTEGER_INFO: + IntegerInfo integerInfo = new IntegerInfo(pool); + int val = Util.byteToInt(iter.getNextNBytes(4)); + integerInfo.setInteger(val); + ret = integerInfo; + break; + case ConstantInfo.FLOAT_INFO: + FloatRefInfo floatInfo = new FloatRefInfo(pool); + ret = floatInfo; + throw new InvalidConstantInfoTypeException("Flat info has not been properly implemented yet"); + //break; + case ConstantInfo.METHOD_INFO: + MethodRefInfo methodInfo = new MethodRefInfo(pool); + int methodClassInfoIndex = Util.byteToInt(iter.getNextNBytes(2)); + methodInfo.setClassInfoIndex(methodClassInfoIndex); + int methodNameAndTypeIndex = Util.byteToInt(iter.getNextNBytes(2)); + methodInfo.setNameAndTypeIndex(methodNameAndTypeIndex); + ret = methodInfo; + break; + case ConstantInfo.NAME_AND_TYPE_INFO: + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + int nameIndex = Util.byteToInt(iter.getNextNBytes(2)); + nameAndTypeInfo.setIndex1(nameIndex); + int descriptorIndex = Util.byteToInt(iter.getNextNBytes(2)); + nameAndTypeInfo.setIndex2(descriptorIndex); + ret = nameAndTypeInfo; + break; + case ConstantInfo.STRING_INFO: + StringInfo stringInfo = new StringInfo(pool); + int index = Util.byteToInt(iter.getNextNBytes(2)); + stringInfo.setIndex(index); + ret = stringInfo; + break; + case ConstantInfo.UTF8_INFO: + UTF8Info utfInfo = new UTF8Info(pool); + int length = Util.byteToInt(iter.getNextNBytes(2)); + utfInfo.setLength(length); + + String utf8Val = new String(iter.getNextNBytes(length), "UTF-8"); + System.out.println("UTF 8 content " + utf8Val); + + utfInfo.setValue(utf8Val); + ret = utfInfo; + break; + + default: + throw new InvalidConstantInfoTypeException(); + } + return ret; + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100755 index 0000000000..9a1a998f41 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + System.out.println("added: " + info.getClass().getName() + " current size; " + constantInfos.size()); + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/FieldRefInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100755 index 0000000000..65475e194c --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/FloatRefInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/FloatRefInfo.java new file mode 100644 index 0000000000..356216a166 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/FloatRefInfo.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.constant; + +public class FloatRefInfo extends ClassInfo{ + + public FloatRefInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + + public int getType(){ + return ConstantInfo.FLOAT_INFO; + } + + +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/IntegerInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/IntegerInfo.java new file mode 100644 index 0000000000..1980de8f2f --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/IntegerInfo.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.constant; + +public class IntegerInfo extends ConstantInfo{ + + int val = 0; + public IntegerInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + + public int getType(){ + return ConstantInfo.INTEGER_INFO; + } + + public void setInteger(int val){ + this.val = val; + } + + public int getInteger(){ + return val; + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/InvalidConstantInfoTypeException.java b/group17/1282579502/src/com/coderising/jvm/constant/InvalidConstantInfoTypeException.java new file mode 100644 index 0000000000..ac33ac7f9c --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/InvalidConstantInfoTypeException.java @@ -0,0 +1,11 @@ +package com.coderising.jvm.constant; + +public class InvalidConstantInfoTypeException extends Exception{ + + public InvalidConstantInfoTypeException(){ + super(); + } + public InvalidConstantInfoTypeException(String message){ + super(message); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/MethodRefInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100755 index 0000000000..7f05870020 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100755 index 0000000000..402f9dec86 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/NullConstantInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100755 index 0000000000..936736016f --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/StringInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/StringInfo.java new file mode 100755 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group17/1282579502/src/com/coderising/jvm/constant/UTF8Info.java b/group17/1282579502/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100755 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + +} diff --git a/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100755 index 0000000000..f312b513ac --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,63 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + + byte[] source = null; + int currentPos = 0; + + public ByteCodeIterator(byte[] source){ + this.source = source; + } + + public byte getNextByte(){ + if(currentPos > source.length -1){ + throw new IndexOutOfBoundsException(); + } + return getByteAt(currentPos++); + } + + public byte[] getNextNBytes(int n){ + byte[] retArray = new byte[n]; + for(int i = 0; isource.length-1){ + throw new IndexOutOfBoundsException(); + } + return source[n]; + } + + + public String getNextHexString(){ + byte b1 = getNextByte(); + int i1 = b1 & 0xFF; + String strVal = Integer.toHexString(i1); + if(strVal.length() < 2){ + strVal = "0".concat(strVal); + } + return strVal; + } + + public String getNextNHexString(int n){ + StringBuilder sb = new StringBuilder(); + while(n-->0){ + sb.append(getNextHexString()); + } + + return sb.toString(); + } + + + + public static void printByteInNumber(byte b){ + int tmp = b; + System.out.println(Integer.toBinaryString(tmp)); + int tmp1 = tmp & 0xFF; + System.out.println(Integer.toBinaryString(tmp1)); + System.out.println(Integer.toHexString(tmp1)); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100755 index 0000000000..7c5809efec --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,96 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantInfoFactory; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.InvalidConstantInfoTypeException; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ClassFileParser { + ClassFile clz = null; + public ClassFile parse(byte[] codes) { + clz = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicHex = iter.getNextNHexString(4); + System.out.println("Magic Number: "+magicHex); + + String minorHex = iter.getNextHexString() + iter.getNextHexString(); + int minorVersionInt = Integer.parseInt(minorHex, 16); + String majorHex = iter.getNextHexString() + iter.getNextHexString(); + int majorVersionInt = Integer.parseInt(majorHex, 16); + clz.setMajorVersion(majorVersionInt);clz.setMinorVersion(minorVersionInt); + System.out.println("Major version: " + majorVersionInt + " minor version: " + minorVersionInt); + clz.setConstPool(parseConstantPool(iter)); + fillClassInfo(clz, clz.getConstantPool()); + return clz; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + return null; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + return null; + + } + + private void fillClassInfo(ClassFile clz, ConstantPool pool){ + ClassIndex newClassIndex = new ClassIndex(); + clz.setClassIndex(newClassIndex); + for(int i = 0; i< pool.getSize(); i++){ + if(pool.getConstantInfo(i) instanceof ClassInfo){ + if(clz.getClzIndex().getThisClassIndex() == 0){ + System.out.println("class"); + clz.getClzIndex().setThisClassIndex(i); + } + else if(clz.getClzIndex().getSuperClassIndex() == 0){ + clz.getClzIndex().setSuperClassIndex(i); + } + else{ + break; + } + } + } + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + String constantPoolSizeHex = iter.getNextHexString() + iter.getNextHexString(); + System.out.println("hex string: " + constantPoolSizeHex + " integer value: " + Integer.parseInt(constantPoolSizeHex, 16)); + int constantCount = Integer.parseInt(constantPoolSizeHex, 16); + ConstantPool constantPool = new ConstantPool(); + constantPool.addConstantInfo(new NullConstantInfo()); + ConstantInfoFactory constantInfoFactory = new ConstantInfoFactory(iter, constantPool); + while(constantCount-- > 1){ + try { + constantInfoFactory.fillNextConstantInfo(); + } catch ( Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + break; + } + + } + + for(int i = 0; i Date: Mon, 10 Apr 2017 14:14:27 +0800 Subject: [PATCH 005/151] =?UTF-8?q?jvm=E5=B8=B8=E9=87=8F=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1264835468/src/assignment/BinaryTree.java | 10 +- .../1264835468/src/assignment/MyStack.java | 39 ------ .../assignment/{MyQueue.java => Queue.java} | 2 +- group17/1264835468/src/assignment/Stack.java | 53 +++++++ .../assignment0326/jvm/clz/AccessFlag.java | 25 ++++ .../src/assignment0326/jvm/clz/ClassFile.java | 77 +++++++++++ .../assignment0326/jvm/clz/ClassIndex.java | 19 +++ .../jvm/constant/ClassInfo.java | 24 ++++ .../jvm/constant/ConstantInfo.java | 29 ++++ .../jvm/constant/ConstantPool.java | 29 ++++ .../jvm/constant/FieldRefInfo.java | 54 ++++++++ .../jvm/constant/MethodRefInfo.java | 55 ++++++++ .../jvm/constant/NameAndTypeInfo.java | 45 ++++++ .../jvm/constant/NullConstantInfo.java | 13 ++ .../jvm/constant/StringInfo.java | 26 ++++ .../assignment0326/jvm/constant/UTF8Info.java | 32 +++++ .../jvm/loader/ByteCodeIterator.java | 34 +++++ .../jvm/loader/ClassFileLoader.java | 25 ++++ .../jvm/loader/ClassFileParser.java | 122 +++++++++++++++++ .../jvm/test/ClassFileLoaderTest.java | 129 ++++++++++++++++-- .../src/assignment0326/jvm/util/Util.java | 24 ++++ .../src/assignment0326/lru/Clock.java | 99 -------------- .../src/assignment0405/StackUtil.java | 104 ++++++++++++++ .../src/assignment0405/StackUtilTest.java | 61 +++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 28 ++++ 25 files changed, 1000 insertions(+), 158 deletions(-) delete mode 100644 group17/1264835468/src/assignment/MyStack.java rename group17/1264835468/src/assignment/{MyQueue.java => Queue.java} (95%) create mode 100644 group17/1264835468/src/assignment/Stack.java create mode 100644 group17/1264835468/src/assignment0326/jvm/clz/AccessFlag.java create mode 100644 group17/1264835468/src/assignment0326/jvm/clz/ClassFile.java create mode 100644 group17/1264835468/src/assignment0326/jvm/clz/ClassIndex.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/ClassInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/ConstantInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/ConstantPool.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/FieldRefInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/MethodRefInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/NameAndTypeInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/NullConstantInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/StringInfo.java create mode 100644 group17/1264835468/src/assignment0326/jvm/constant/UTF8Info.java create mode 100644 group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java create mode 100644 group17/1264835468/src/assignment0326/jvm/loader/ClassFileParser.java create mode 100644 group17/1264835468/src/assignment0326/jvm/util/Util.java delete mode 100644 group17/1264835468/src/assignment0326/lru/Clock.java create mode 100644 group17/1264835468/src/assignment0405/StackUtil.java create mode 100644 group17/1264835468/src/assignment0405/StackUtilTest.java create mode 100644 group17/1264835468/src/com/coderising/jvm/test/EmployeeV1.java diff --git a/group17/1264835468/src/assignment/BinaryTree.java b/group17/1264835468/src/assignment/BinaryTree.java index 1d76a7ce2c..882a87f6ed 100644 --- a/group17/1264835468/src/assignment/BinaryTree.java +++ b/group17/1264835468/src/assignment/BinaryTree.java @@ -53,10 +53,10 @@ public String toString() { * */ private class BFSNodeQueue { - private MyQueue> nodeQueue; + private Queue> nodeQueue; public BFSNodeQueue() { - nodeQueue = new MyQueue<>(); + nodeQueue = new Queue<>(); } public boolean isEmpty() { @@ -79,9 +79,9 @@ public BinaryTreeNode deQueue() { } // 把所有出队节点放进另一个队列中 - public MyQueue> getResult() { + public Queue> getResult() { prepare(); - MyQueue> result = new MyQueue<>(); + Queue> result = new Queue<>(); while (!isEmpty()) { result.enQueue(deQueue()); } @@ -121,7 +121,7 @@ private class BFSIterator implements Iterator> { Iterator> iterator; public BFSIterator() { - MyQueue> BFSQueue = new BFSNodeQueue().getResult(); + Queue> BFSQueue = new BFSNodeQueue().getResult(); list = new MyArrayList<>(); while (!BFSQueue.isEmpty()) { list.add(BFSQueue.deQueue()); diff --git a/group17/1264835468/src/assignment/MyStack.java b/group17/1264835468/src/assignment/MyStack.java deleted file mode 100644 index 0c3d30337b..0000000000 --- a/group17/1264835468/src/assignment/MyStack.java +++ /dev/null @@ -1,39 +0,0 @@ -package assignment; - -public class MyStack { - private MyArrayList elementData = new MyArrayList<>(); - - public void push(T o) { - elementData.add(o); - } - - public T pop() { - if (!isEmpty()) { - T data = elementData.remove(elementData.size() - 1); - return data; - } - throw new StackIsEmptyException(); - } - - public T peek() { - return elementData.get(elementData.size() - 1); - } - - public boolean isEmpty() { - return elementData.size() == 0; - } - - public int size() { - return elementData.size(); - } -} - -class StackIsEmptyException extends RuntimeException { - public StackIsEmptyException() { - super(); - } - - public StackIsEmptyException(String string) { - super(string); - } -} diff --git a/group17/1264835468/src/assignment/MyQueue.java b/group17/1264835468/src/assignment/Queue.java similarity index 95% rename from group17/1264835468/src/assignment/MyQueue.java rename to group17/1264835468/src/assignment/Queue.java index c5e3e8ce88..eb3b474e75 100644 --- a/group17/1264835468/src/assignment/MyQueue.java +++ b/group17/1264835468/src/assignment/Queue.java @@ -1,6 +1,6 @@ package assignment; -public class MyQueue { +public class Queue { private MyLinkedList elementData = new MyLinkedList<>(); public void enQueue(T o) { diff --git a/group17/1264835468/src/assignment/Stack.java b/group17/1264835468/src/assignment/Stack.java new file mode 100644 index 0000000000..9100544ee3 --- /dev/null +++ b/group17/1264835468/src/assignment/Stack.java @@ -0,0 +1,53 @@ +package assignment; + +public class Stack { + private MyArrayList elementData = new MyArrayList<>(); + + public void push(T o) { + elementData.add(o); + } + + public T pop() { + if (!isEmpty()) { + T data = elementData.remove(elementData.size() - 1); + return data; + } + throw new EmptyStackException(); + } + + public T peek() { + if(!isEmpty()) + return elementData.get(elementData.size() - 1); + throw new EmptyStackException(); + } + + public boolean isEmpty() { + return elementData.size() == 0; + } + + public int size() { + return elementData.size(); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = elementData.size()-1; i >=0; i--) { + stringBuilder.append(elementData.get(i)); + if (i != 0) { + stringBuilder.append(", "); + } + } + return stringBuilder.toString(); + } +} + +class EmptyStackException extends RuntimeException { + public EmptyStackException() { + super(); + } + + public EmptyStackException(String string) { + super(string); + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/clz/AccessFlag.java b/group17/1264835468/src/assignment0326/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..f95bc2e902 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package assignment0326.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group17/1264835468/src/assignment0326/jvm/clz/ClassFile.java b/group17/1264835468/src/assignment0326/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2cb501297d --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/clz/ClassFile.java @@ -0,0 +1,77 @@ +package assignment0326.jvm.clz; + + +import assignment0326.jvm.constant.ClassInfo; +import assignment0326.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + 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()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/clz/ClassIndex.java b/group17/1264835468/src/assignment0326/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..a3e5c3d350 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package assignment0326.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group17/1264835468/src/assignment0326/jvm/constant/ClassInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..4a7397478e --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package assignment0326.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/ConstantInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..f6acdc0580 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package assignment0326.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/ConstantPool.java b/group17/1264835468/src/assignment0326/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..96f40534da --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package assignment0326.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/FieldRefInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..d0beb7f1f2 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package assignment0326.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/MethodRefInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..3678f46c39 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package assignment0326.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/NameAndTypeInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..7659657b94 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package assignment0326.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/NullConstantInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..d8f8bda26e --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package assignment0326.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/StringInfo.java b/group17/1264835468/src/assignment0326/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..eb6b9b4d7e --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package assignment0326.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group17/1264835468/src/assignment0326/jvm/constant/UTF8Info.java b/group17/1264835468/src/assignment0326/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..80f3389bd9 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package assignment0326.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + +} diff --git a/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java b/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..e9b9fdaf2e --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,34 @@ +package assignment0326.jvm.loader; + +public class ByteCodeIterator { + int curPos; + byte[] bytes; + + public ByteCodeIterator(byte[] bytes) { + curPos=0; + this.bytes = bytes; + } + + public byte nextByte(){ + return bytes[curPos++]; + } + public int nextByteToInt(){ + return Byte.toUnsignedInt(nextByte()); + } + public int next2BytesToInt(){ + int hi=Byte.toUnsignedInt(nextByte()); + int lo = Byte.toUnsignedInt(nextByte()); + int i=hi<<8|lo; + return i; + } + public byte[] nextNBytes(int n){ + byte[] bytes = new byte[n]; + for (int i = 0; i < n; i++) { + bytes[i]=nextByte(); + } + return bytes; + } + public void skip(int n){ + curPos+=n; + } +} diff --git a/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java index a5add91113..4aaf67a2d1 100644 --- a/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java +++ b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java @@ -1,9 +1,13 @@ package assignment0326.jvm.loader; +import assignment0326.jvm.clz.ClassFile; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -38,6 +42,9 @@ public byte[] readBinaryCode(String className) { public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } clzPaths.add(path); } @@ -53,7 +60,25 @@ public String getClassPath(){ } + private byte[] loadClassFile(String clzFileName) { + + try { + + return Files.readAllBytes(Paths.get(clzFileName)); + + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } } diff --git a/group17/1264835468/src/assignment0326/jvm/loader/ClassFileParser.java b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..92aaa75d3a --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileParser.java @@ -0,0 +1,122 @@ +package assignment0326.jvm.loader; + +import assignment0326.jvm.clz.AccessFlag; +import assignment0326.jvm.clz.ClassFile; +import assignment0326.jvm.clz.ClassIndex; +import assignment0326.jvm.constant.*; + + +public class ClassFileParser { + + private ConstantPool constantPool; + public ClassFile parse(byte[] codes) { + ClassFile classFile=new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(codes); + iterator.skip(4); + + classFile.setMinorVersion(iterator.next2BytesToInt()); + classFile.setMajorVersion(iterator.next2BytesToInt()); + + classFile.setConstPool(parseConstantPool(iterator)); + + classFile.setAccessFlag(parseAccessFlag(iterator)); + + classFile.setClassIndex(parseClassIndex(iterator)); + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.next2BytesToInt()); + return flag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex classIndex=new ClassIndex(); + classIndex.setThisClassIndex(iter.next2BytesToInt()); + classIndex.setSuperClassIndex(iter.next2BytesToInt()); + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + constantPool=new ConstantPool(); + int size=iter.next2BytesToInt(); + constantPool.addConstantInfo(new NullConstantInfo()); + for (int i = 0; i < size-1; i++) { + parseConstant(iter); + } + return constantPool; + } + + private void parseConstant(ByteCodeIterator iter) { + int flag=iter.nextByteToInt(); + ConstantInfo constantInfo; + switch (flag){ + case ConstantInfo.UTF8_INFO: + constantInfo=parseUTF8Info(iter); + break; + case ConstantInfo.CLASS_INFO: + constantInfo = parseClassInfo(iter); + break; + case ConstantInfo.STRING_INFO: + constantInfo = parseStringInfo(iter); + break; + case ConstantInfo.FIELD_INFO: + constantInfo = parseFieldInfo(iter); + break; + case ConstantInfo.METHOD_INFO: + constantInfo = parseMethodInfo(iter); + break; + case ConstantInfo.NAME_AND_TYPE_INFO: + constantInfo = parseNameAndTypeInfo(iter); + break; + default: + throw new RuntimeException("Unsupported flag"); + } + constantPool.addConstantInfo(constantInfo); + } + + private ConstantInfo parseUTF8Info(ByteCodeIterator iter) { + UTF8Info utf8Info = new UTF8Info(constantPool); + int length=iter.next2BytesToInt(); + String value=new String(iter.nextNBytes(length)); + utf8Info.setLength(length); + utf8Info.setValue(value); + return utf8Info; + } + + private ConstantInfo parseClassInfo(ByteCodeIterator iter) { + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(iter.next2BytesToInt()); + return classInfo; + } + + private ConstantInfo parseStringInfo(ByteCodeIterator iter) { + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(iter.next2BytesToInt()); + return stringInfo; + } + + private ConstantInfo parseFieldInfo(ByteCodeIterator iter) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(iter.next2BytesToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.next2BytesToInt()); + return fieldRefInfo; + } + + private ConstantInfo parseMethodInfo(ByteCodeIterator iter) { + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(iter.next2BytesToInt()); + methodRefInfo.setNameAndTypeIndex(iter.next2BytesToInt()); + return methodRefInfo; + } + + private ConstantInfo parseNameAndTypeInfo(ByteCodeIterator iter) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(iter.next2BytesToInt()); + nameAndTypeInfo.setIndex2(iter.next2BytesToInt()); + return nameAndTypeInfo; + } + + +} diff --git a/group17/1264835468/src/assignment0326/jvm/test/ClassFileLoaderTest.java b/group17/1264835468/src/assignment0326/jvm/test/ClassFileLoaderTest.java index 5ebb4075a6..3b507732bb 100644 --- a/group17/1264835468/src/assignment0326/jvm/test/ClassFileLoaderTest.java +++ b/group17/1264835468/src/assignment0326/jvm/test/ClassFileLoaderTest.java @@ -4,6 +4,9 @@ * Created by Administrator on 2017/3/30. */ +import assignment0326.jvm.clz.ClassFile; +import assignment0326.jvm.clz.ClassIndex; +import assignment0326.jvm.constant.*; import assignment0326.jvm.loader.ClassFileLoader; import org.junit.After; import org.junit.Assert; @@ -11,16 +14,23 @@ import org.junit.Test; - - - public class ClassFileLoaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; static String path1 = "D:\\GitHub\\group17\\1264835468\\bin"; static String path2 = "C:\\Temp"; + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + //clzFile.print(); + } @Before public void setUp() throws Exception { @@ -31,7 +41,7 @@ public void tearDown() throws Exception { } @Test - public void testClassPath(){ + public void testClassPath() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); @@ -39,7 +49,7 @@ public void testClassPath(){ String clzPath = loader.getClassPath(); - Assert.assertEquals(path1+";"+path2,clzPath); + Assert.assertEquals(path1 + ";" + path2, clzPath); } @@ -60,12 +70,12 @@ public void testClassFileLength() { @Test - public void testMagicNumber(){ + public void testMagicNumber() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); String className = "assignment0326.jvm.test.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); - byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; String acctualValue = this.byteToHexString(codes); @@ -74,17 +84,13 @@ public void testMagicNumber(){ } - - - - - private String byteToHexString(byte[] codes ){ + private String byteToHexString(byte[] codes) { StringBuffer buffer = new StringBuffer(); - for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + + @Test + public void testClassIndex() { + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + } \ No newline at end of file diff --git a/group17/1264835468/src/assignment0326/jvm/util/Util.java b/group17/1264835468/src/assignment0326/jvm/util/Util.java new file mode 100644 index 0000000000..5855550bf8 --- /dev/null +++ b/group17/1264835468/src/assignment0326/jvm/util/Util.java @@ -0,0 +1,24 @@ +package assignment0326.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i strings=new ArrayList<>(); - for (int i = 0; i <10; i++) { - strings.add(String.valueOf(new Random().nextInt(3000))); - } - System.out.println(strings); - System.out.println(strings.stream().map(s-> s.charAt(0)).sorted().distinct().limit(5).collect(Collectors.toList())); - } - - public int findMinDifference(List timePoints) { - List list=new ArrayList<>(); - - for (String s:timePoints) { - list.add(parse(s)); - } - Collections.sort(list); - int min=Integer.MAX_VALUE; - for (int i = 0; i < list.size()-1; i++) { - min=Math.min(min,Math.min(Math.abs(list.get(i+1)-list.get(i)),24*60-Math.abs(list.get(i+1)-list.get(i)))); - } - return min; - } - - private Integer parse(String s) { - return Integer.parseInt(s.substring(0, 2)) * 60 + Integer.parseInt(s.substring(3, 5)); - } -} diff --git a/group17/1264835468/src/assignment0405/StackUtil.java b/group17/1264835468/src/assignment0405/StackUtil.java new file mode 100644 index 0000000000..469a13f9a9 --- /dev/null +++ b/group17/1264835468/src/assignment0405/StackUtil.java @@ -0,0 +1,104 @@ +package assignment0405; + +import assignment.Stack; + +/** + * Created by Administrator on 2017/4/6. + */ +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack stack1 = new Stack(); + Stack stack2 = new Stack(); + popAllToAnotherStack(s, stack1); + popAllToAnotherStack(stack1, stack2); + popAllToAnotherStack(stack2, s); + } + + private static void popAllToAnotherStack(Stack s, Stack another) { + while (!s.isEmpty()) { + another.push(s.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack stack2 = new Stack(); + while (!s.isEmpty()) { + Object top = s.pop(); + if (!top.equals(o)) { + stack2.push(top); + } + } + popAllToAnotherStack(stack2, s); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if(len>s.size()) + throw new RuntimeException("Stack size:" + s.size() + " < " + len); + Object[] objects = new Object[len]; + for (int i = 0; i < len; i++) { + objects[i] = s.pop(); + } + for (int i = len - 1; i >= 0; i--) { + s.push(objects[i]); + } + return objects; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + Stack stack = new Stack<>(); + + for (char c : s.toCharArray()) { + if (isLeft(c)) { + stack.push(c); + continue; + } + if (isRight(c)) { + if (stack.isEmpty() || !match(stack.pop(), c)) { + return false; + } + } + } + return stack.isEmpty(); + } + + private static boolean isLeft(char c) { + return c == '[' || c == '(' || c == '{'; + } + + private static boolean isRight(char c) { + return c == ']' || c == ')' || c == '}'; + } + + private static boolean match(char c1, char c2) { + return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']') || (c1 == '{' && c2 == '}'); + } + + +} diff --git a/group17/1264835468/src/assignment0405/StackUtilTest.java b/group17/1264835468/src/assignment0405/StackUtilTest.java new file mode 100644 index 0000000000..58be1302f6 --- /dev/null +++ b/group17/1264835468/src/assignment0405/StackUtilTest.java @@ -0,0 +1,61 @@ +package assignment0405; + +import assignment.Stack; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/9. + */ +public class StackUtilTest { + @Test + public void reverse() throws Exception { + Stack stack = new Stack(); + pushAll(stack, 1, 2, 3, 4); + Assert.assertEquals("4, 3, 2, 1", stack.toString()); + StackUtil.reverse(stack); + Assert.assertEquals("1, 2, 3, 4", stack.toString()); + StackUtil.reverse(stack); + Assert.assertEquals("4, 3, 2, 1", stack.toString()); + } + + + @Test + public void remove() throws Exception { + Stack stack = new Stack(); + pushAll(stack, 0, 1, 2, 3); + StackUtil.remove(stack, 1); + Assert.assertEquals("3, 2, 0", stack.toString()); + pushAll(stack, 4, 5, 6, 5); + Assert.assertEquals("5, 6, 5, 4, 3, 2, 0", stack.toString()); + StackUtil.remove(stack, 5); + Assert.assertEquals("6, 4, 3, 2, 0", stack.toString()); + + } + + @Test(expected = RuntimeException.class) + public void getTop() throws Exception { + Stack stack = new Stack(); + pushAll(stack, 1, 2, 3, 4, 5); + Assert.assertArrayEquals(new Object[]{5, 4, 3}, StackUtil.getTop(stack, 3)); + Assert.assertArrayEquals(new Object[]{5}, StackUtil.getTop(stack, 1)); + Assert.assertArrayEquals(new Object[]{5, 4, 3, 2, 1}, StackUtil.getTop(stack, 5)); + //异常 + StackUtil.getTop(stack, 6); + } + + @Test + public void isValidPairs() throws Exception { + Assert.assertTrue(StackUtil.isValidPairs("()[]{}([])")); + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + Assert.assertFalse(StackUtil.isValidPairs("((a)[]{b(c)}")); + } + + private void pushAll(Stack s, Object... objects) { + for (Object object : objects) { + s.push(object); + } + } + +} \ No newline at end of file diff --git a/group17/1264835468/src/com/coderising/jvm/test/EmployeeV1.java b/group17/1264835468/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..8ba6ebd501 --- /dev/null +++ b/group17/1264835468/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file From e93808e860d874b3281784886ec2d230f05813bb Mon Sep 17 00:00:00 2001 From: liuxianan// <1264835468@qq.com> Date: Mon, 10 Apr 2017 14:55:02 +0800 Subject: [PATCH 006/151] =?UTF-8?q?jvm=E5=B8=B8=E9=87=8F=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jvm/loader/ByteCodeIterator.java | 28 ++- .../jvm/loader/ClassFileLoader.java | 65 +++-- .../jvm/loader/ClassFileParser.java | 229 +++++++++--------- .../src/assignment0405/StackUtil.java | 6 +- 4 files changed, 173 insertions(+), 155 deletions(-) diff --git a/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java b/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java index e9b9fdaf2e..09d87c13b6 100644 --- a/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java +++ b/group17/1264835468/src/assignment0326/jvm/loader/ByteCodeIterator.java @@ -5,30 +5,38 @@ public class ByteCodeIterator { byte[] bytes; public ByteCodeIterator(byte[] bytes) { - curPos=0; + curPos = 0; this.bytes = bytes; } - public byte nextByte(){ + public boolean hasNext() { + return !(curPos >= bytes.length); + } + + public byte nextByte() { return bytes[curPos++]; } - public int nextByteToInt(){ + + public int nextByteToInt() { return Byte.toUnsignedInt(nextByte()); } - public int next2BytesToInt(){ - int hi=Byte.toUnsignedInt(nextByte()); + + public int next2BytesToInt() { + int hi = Byte.toUnsignedInt(nextByte()); int lo = Byte.toUnsignedInt(nextByte()); - int i=hi<<8|lo; + int i = hi << 8 | lo; return i; } - public byte[] nextNBytes(int n){ + + public byte[] nextNBytes(int n) { byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { - bytes[i]=nextByte(); + bytes[i] = nextByte(); } return bytes; } - public void skip(int n){ - curPos+=n; + + public void skip(int n) { + curPos += n; } } diff --git a/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java index 4aaf67a2d1..3b05a1f761 100644 --- a/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java +++ b/group17/1264835468/src/assignment0326/jvm/loader/ClassFileLoader.java @@ -17,47 +17,46 @@ public class ClassFileLoader { - private List clzPaths = new ArrayList(); - - public byte[] readBinaryCode(String className) { - String path = className.replace(".", File.separator); - File classFile=null; - for (String p: clzPaths) { - classFile=new File(p+File.separator+path+".class"); - if(classFile.exists()) - break; - } - if(classFile==null) - throw new RuntimeException("no such class file"); - - byte[] bytes=new byte[(int)classFile.length()]; - try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(classFile))){ - bufferedInputStream.read(bytes, 0, bytes.length); - - } catch (IOException e) { - e.printStackTrace(); - } - return bytes; + private List clzPaths = new ArrayList<>(); + + public byte[] readBinaryCode(String className) { + String path = className.replace(".", File.separator); + File classFile = null; + for (String p : clzPaths) { + classFile = new File(p + File.separator + path + ".class"); + if (classFile.exists()) + break; } + if (classFile == null) + throw new RuntimeException("no such class file"); + byte[] bytes = new byte[(int) classFile.length()]; + try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(classFile))) { + bufferedInputStream.read(bytes, 0, bytes.length); - public void addClassPath(String path) { - if(this.clzPaths.contains(path)){ - return; - } - clzPaths.add(path); + } catch (IOException e) { + e.printStackTrace(); } + return bytes; + } + public void addClassPath(String path) { + if (this.clzPaths.contains(path)) { + return; + } + clzPaths.add(path); + } + - public String getClassPath(){ - StringBuilder stringBuilder=new StringBuilder(); - for (int i = 0; i s.size()) + if (len > s.size()) throw new RuntimeException("Stack size:" + s.size() + " < " + len); Object[] objects = new Object[len]; for (int i = 0; i < len; i++) { @@ -96,8 +96,8 @@ private static boolean isRight(char c) { return c == ']' || c == ')' || c == '}'; } - private static boolean match(char c1, char c2) { - return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']') || (c1 == '{' && c2 == '}'); + private static boolean match(char left, char right) { + return (left == '(' && right == ')') || (left == '[' && right == ']') || (left == '{' && right == '}'); } From cae45cdc6480ce170cd0ddb5560ad6b2503614a7 Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Mon, 10 Apr 2017 15:10:09 +0800 Subject: [PATCH 007/151] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=BB=93=E6=9E=84=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=AC=AC=E5=85=AD=E6=AC=A1=E4=BD=9C=E4=B8=9A=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group27/383117348/.classpath | 3 +- .../coderising/download/DownloadThread.java | 0 .../coderising/download/FileDownloader.java | 0 .../download/FileDownloaderTest.java | 0 .../coderising/download/api/Connection.java | 0 .../download/api/ConnectionException.java | 0 .../download/api/ConnectionManager.java | 0 .../download/api/DownloadListener.java | 0 .../download/impl/ConnectionImpl.java | 0 .../download/impl/ConnectionManagerImpl.java | 0 .../coderising/litestruts/LoginAction.java | 0 .../com/coderising/litestruts/Struts.java | 0 .../com/coderising/litestruts/StrutsTest.java | 0 .../com/coderising/litestruts/View.java | 0 .../com/coderising/litestruts/struts.xml | 0 .../com/coding/basic/BinaryTreeNode.java | 0 .../com/coding/basic/Iterator.java | 0 .../com/coding/basic/List.java | 0 .../com/coding/basic/Queue.java | 0 .../com/coding/basic/array/ArrayList.java | 0 .../com/coding/basic/array/ArrayUtil.java | 0 .../coding/basic/linklist/LRUPageFrame.java | 0 .../basic/linklist/LRUPageFrameTest.java | 0 .../com/coding/basic/linklist/LinkedList.java | 0 .../com/coding/basic/stack/Stack.java | 0 .../com/coding/basic/stack/StackUtil.java | 0 .../coding/basic/stack/expr/InfixExpr.java | 15 ++++ .../basic/stack/expr/InfixExprTest.java | 46 ++++++++++++ .../basic/stack/test/StackUtilTest.java | 0 .../coderising/jvm/attr/AttributeInfo.java | 17 +++++ .../com/coderising/jvm/attr/CodeAttr.java | 49 ++++++++++++ .../coderising/jvm/attr/LineNumberTable.java | 46 ++++++++++++ .../jvm/attr/LocalVariableItem.java | 39 ++++++++++ .../jvm/attr/LocalVariableTable.java | 25 +++++++ .../coderising/jvm/attr/StackMapTable.java | 29 ++++++++ .../com/coderising/jvm/clz/AccessFlag.java | 0 .../com/coderising/jvm/clz/ClassFile.java | 24 ++++-- .../com/coderising/jvm/clz/ClassIndex.java | 0 .../coderising/jvm/constant/ClassInfo.java | 0 .../coderising/jvm/constant/ConstantInfo.java | 0 .../coderising/jvm/constant/ConstantPool.java | 0 .../coderising/jvm/constant/FieldRefInfo.java | 0 .../coderising/jvm/constant/FloatInfo.java | 0 .../coderising/jvm/constant/IntegerInfo.java | 0 .../jvm/constant/MethodRefInfo.java | 0 .../jvm/constant/NameAndTypeInfo.java | 0 .../jvm/constant/NullConstantInfo.java | 0 .../coderising/jvm/constant/StringInfo.java | 0 .../com/coderising/jvm/constant/UTF8Info.java | 0 .../com/coderising/jvm/field/Field.java | 31 ++++++++ .../jvm/loader/ByteCodeIterator.java | 14 ++++ .../jvm/loader/ClassFileLoader.java | 0 .../jvm/loader/ClassFileLoader_backup.java | 0 .../jvm/loader/ClassFileParser.java | 14 ++++ .../com/coderising/jvm/method/Method.java | 52 +++++++++++++ .../jvm/test/ClassFileloaderTest.java | 74 +++++++++++++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 0 .../com/coderising/jvm/util/Util.java | 0 58 files changed, 472 insertions(+), 6 deletions(-) rename group27/383117348/{src => data-structure}/com/coderising/download/DownloadThread.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/FileDownloader.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/FileDownloaderTest.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/api/Connection.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/api/ConnectionException.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/api/ConnectionManager.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/api/DownloadListener.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/impl/ConnectionImpl.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/download/impl/ConnectionManagerImpl.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/litestruts/LoginAction.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/litestruts/Struts.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/litestruts/StrutsTest.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/litestruts/View.java (100%) rename group27/383117348/{src => data-structure}/com/coderising/litestruts/struts.xml (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/BinaryTreeNode.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/Iterator.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/List.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/Queue.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/array/ArrayList.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/array/ArrayUtil.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/linklist/LRUPageFrame.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/linklist/LRUPageFrameTest.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/linklist/LinkedList.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/stack/Stack.java (100%) rename group27/383117348/{src => data-structure}/com/coding/basic/stack/StackUtil.java (100%) create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExprTest.java rename group27/383117348/{src => data-structure}/com/coding/basic/stack/test/StackUtilTest.java (100%) create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/attr/StackMapTable.java rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/clz/AccessFlag.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/clz/ClassFile.java (74%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/clz/ClassIndex.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/ClassInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/ConstantInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/ConstantPool.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/FieldRefInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/FloatInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/IntegerInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/MethodRefInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/NameAndTypeInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/NullConstantInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/StringInfo.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/constant/UTF8Info.java (100%) create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/loader/ByteCodeIterator.java (76%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/loader/ClassFileLoader.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/loader/ClassFileLoader_backup.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/loader/ClassFileParser.java (92%) create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/test/ClassFileloaderTest.java (71%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/test/EmployeeV1.java (100%) rename group27/383117348/{src => mini-jvm}/com/coderising/jvm/util/Util.java (100%) diff --git a/group27/383117348/.classpath b/group27/383117348/.classpath index a96bb3c428..58f336f5a2 100644 --- a/group27/383117348/.classpath +++ b/group27/383117348/.classpath @@ -1,7 +1,8 @@ - + + diff --git a/group27/383117348/src/com/coderising/download/DownloadThread.java b/group27/383117348/data-structure/com/coderising/download/DownloadThread.java similarity index 100% rename from group27/383117348/src/com/coderising/download/DownloadThread.java rename to group27/383117348/data-structure/com/coderising/download/DownloadThread.java diff --git a/group27/383117348/src/com/coderising/download/FileDownloader.java b/group27/383117348/data-structure/com/coderising/download/FileDownloader.java similarity index 100% rename from group27/383117348/src/com/coderising/download/FileDownloader.java rename to group27/383117348/data-structure/com/coderising/download/FileDownloader.java diff --git a/group27/383117348/src/com/coderising/download/FileDownloaderTest.java b/group27/383117348/data-structure/com/coderising/download/FileDownloaderTest.java similarity index 100% rename from group27/383117348/src/com/coderising/download/FileDownloaderTest.java rename to group27/383117348/data-structure/com/coderising/download/FileDownloaderTest.java diff --git a/group27/383117348/src/com/coderising/download/api/Connection.java b/group27/383117348/data-structure/com/coderising/download/api/Connection.java similarity index 100% rename from group27/383117348/src/com/coderising/download/api/Connection.java rename to group27/383117348/data-structure/com/coderising/download/api/Connection.java diff --git a/group27/383117348/src/com/coderising/download/api/ConnectionException.java b/group27/383117348/data-structure/com/coderising/download/api/ConnectionException.java similarity index 100% rename from group27/383117348/src/com/coderising/download/api/ConnectionException.java rename to group27/383117348/data-structure/com/coderising/download/api/ConnectionException.java diff --git a/group27/383117348/src/com/coderising/download/api/ConnectionManager.java b/group27/383117348/data-structure/com/coderising/download/api/ConnectionManager.java similarity index 100% rename from group27/383117348/src/com/coderising/download/api/ConnectionManager.java rename to group27/383117348/data-structure/com/coderising/download/api/ConnectionManager.java diff --git a/group27/383117348/src/com/coderising/download/api/DownloadListener.java b/group27/383117348/data-structure/com/coderising/download/api/DownloadListener.java similarity index 100% rename from group27/383117348/src/com/coderising/download/api/DownloadListener.java rename to group27/383117348/data-structure/com/coderising/download/api/DownloadListener.java diff --git a/group27/383117348/src/com/coderising/download/impl/ConnectionImpl.java b/group27/383117348/data-structure/com/coderising/download/impl/ConnectionImpl.java similarity index 100% rename from group27/383117348/src/com/coderising/download/impl/ConnectionImpl.java rename to group27/383117348/data-structure/com/coderising/download/impl/ConnectionImpl.java diff --git a/group27/383117348/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group27/383117348/data-structure/com/coderising/download/impl/ConnectionManagerImpl.java similarity index 100% rename from group27/383117348/src/com/coderising/download/impl/ConnectionManagerImpl.java rename to group27/383117348/data-structure/com/coderising/download/impl/ConnectionManagerImpl.java diff --git a/group27/383117348/src/com/coderising/litestruts/LoginAction.java b/group27/383117348/data-structure/com/coderising/litestruts/LoginAction.java similarity index 100% rename from group27/383117348/src/com/coderising/litestruts/LoginAction.java rename to group27/383117348/data-structure/com/coderising/litestruts/LoginAction.java diff --git a/group27/383117348/src/com/coderising/litestruts/Struts.java b/group27/383117348/data-structure/com/coderising/litestruts/Struts.java similarity index 100% rename from group27/383117348/src/com/coderising/litestruts/Struts.java rename to group27/383117348/data-structure/com/coderising/litestruts/Struts.java diff --git a/group27/383117348/src/com/coderising/litestruts/StrutsTest.java b/group27/383117348/data-structure/com/coderising/litestruts/StrutsTest.java similarity index 100% rename from group27/383117348/src/com/coderising/litestruts/StrutsTest.java rename to group27/383117348/data-structure/com/coderising/litestruts/StrutsTest.java diff --git a/group27/383117348/src/com/coderising/litestruts/View.java b/group27/383117348/data-structure/com/coderising/litestruts/View.java similarity index 100% rename from group27/383117348/src/com/coderising/litestruts/View.java rename to group27/383117348/data-structure/com/coderising/litestruts/View.java diff --git a/group27/383117348/src/com/coderising/litestruts/struts.xml b/group27/383117348/data-structure/com/coderising/litestruts/struts.xml similarity index 100% rename from group27/383117348/src/com/coderising/litestruts/struts.xml rename to group27/383117348/data-structure/com/coderising/litestruts/struts.xml diff --git a/group27/383117348/src/com/coding/basic/BinaryTreeNode.java b/group27/383117348/data-structure/com/coding/basic/BinaryTreeNode.java similarity index 100% rename from group27/383117348/src/com/coding/basic/BinaryTreeNode.java rename to group27/383117348/data-structure/com/coding/basic/BinaryTreeNode.java diff --git a/group27/383117348/src/com/coding/basic/Iterator.java b/group27/383117348/data-structure/com/coding/basic/Iterator.java similarity index 100% rename from group27/383117348/src/com/coding/basic/Iterator.java rename to group27/383117348/data-structure/com/coding/basic/Iterator.java diff --git a/group27/383117348/src/com/coding/basic/List.java b/group27/383117348/data-structure/com/coding/basic/List.java similarity index 100% rename from group27/383117348/src/com/coding/basic/List.java rename to group27/383117348/data-structure/com/coding/basic/List.java diff --git a/group27/383117348/src/com/coding/basic/Queue.java b/group27/383117348/data-structure/com/coding/basic/Queue.java similarity index 100% rename from group27/383117348/src/com/coding/basic/Queue.java rename to group27/383117348/data-structure/com/coding/basic/Queue.java diff --git a/group27/383117348/src/com/coding/basic/array/ArrayList.java b/group27/383117348/data-structure/com/coding/basic/array/ArrayList.java similarity index 100% rename from group27/383117348/src/com/coding/basic/array/ArrayList.java rename to group27/383117348/data-structure/com/coding/basic/array/ArrayList.java diff --git a/group27/383117348/src/com/coding/basic/array/ArrayUtil.java b/group27/383117348/data-structure/com/coding/basic/array/ArrayUtil.java similarity index 100% rename from group27/383117348/src/com/coding/basic/array/ArrayUtil.java rename to group27/383117348/data-structure/com/coding/basic/array/ArrayUtil.java diff --git a/group27/383117348/src/com/coding/basic/linklist/LRUPageFrame.java b/group27/383117348/data-structure/com/coding/basic/linklist/LRUPageFrame.java similarity index 100% rename from group27/383117348/src/com/coding/basic/linklist/LRUPageFrame.java rename to group27/383117348/data-structure/com/coding/basic/linklist/LRUPageFrame.java diff --git a/group27/383117348/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group27/383117348/data-structure/com/coding/basic/linklist/LRUPageFrameTest.java similarity index 100% rename from group27/383117348/src/com/coding/basic/linklist/LRUPageFrameTest.java rename to group27/383117348/data-structure/com/coding/basic/linklist/LRUPageFrameTest.java diff --git a/group27/383117348/src/com/coding/basic/linklist/LinkedList.java b/group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java similarity index 100% rename from group27/383117348/src/com/coding/basic/linklist/LinkedList.java rename to group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java diff --git a/group27/383117348/src/com/coding/basic/stack/Stack.java b/group27/383117348/data-structure/com/coding/basic/stack/Stack.java similarity index 100% rename from group27/383117348/src/com/coding/basic/stack/Stack.java rename to group27/383117348/data-structure/com/coding/basic/stack/Stack.java diff --git a/group27/383117348/src/com/coding/basic/stack/StackUtil.java b/group27/383117348/data-structure/com/coding/basic/stack/StackUtil.java similarity index 100% rename from group27/383117348/src/com/coding/basic/stack/StackUtil.java rename to group27/383117348/data-structure/com/coding/basic/stack/StackUtil.java diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..cc084db36d --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,15 @@ +package com.coding.basic.stack.expr; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + return 0.0f; + } + +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExprTest.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..e2de427e62 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,46 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixExprTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group27/383117348/src/com/coding/basic/stack/test/StackUtilTest.java b/group27/383117348/data-structure/com/coding/basic/stack/test/StackUtilTest.java similarity index 100% rename from group27/383117348/src/com/coding/basic/stack/test/StackUtilTest.java rename to group27/383117348/data-structure/com/coding/basic/stack/test/StackUtilTest.java diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..85156946eb --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.attr; + +public 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/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..63f4503244 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,49 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..0e072f6d66 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,46 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo{ + List 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) { + + return null; + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..3eb2654e36 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..e69728e6aa --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + return null; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/StackMapTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..70387e2bb2 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.attr; + +import com.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.nextU2Int(); + int len = iter.nextU4Integer(); + 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/group27/383117348/src/com/coderising/jvm/clz/AccessFlag.java b/group27/383117348/mini-jvm/com/coderising/jvm/clz/AccessFlag.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/clz/AccessFlag.java rename to group27/383117348/mini-jvm/com/coderising/jvm/clz/AccessFlag.java diff --git a/group27/383117348/src/com/coderising/jvm/clz/ClassFile.java b/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java similarity index 74% rename from group27/383117348/src/com/coderising/jvm/clz/ClassFile.java rename to group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java index 1b5a8b95a6..9827aa2937 100644 --- a/group27/383117348/src/com/coderising/jvm/clz/ClassFile.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java @@ -1,7 +1,12 @@ package com.coderising.jvm.clz; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFile { @@ -11,7 +16,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; @@ -22,9 +28,6 @@ public AccessFlag getAccessFlag() { public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - - public ConstantPool getConstantPool() { return pool; } @@ -48,7 +51,18 @@ public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - + 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 print(){ diff --git a/group27/383117348/src/com/coderising/jvm/clz/ClassIndex.java b/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassIndex.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/clz/ClassIndex.java rename to group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassIndex.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/ClassInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/ClassInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/ConstantInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/ConstantPool.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/ConstantPool.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/FieldRefInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/FloatInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/FloatInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/IntegerInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/IntegerInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/MethodRefInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/NameAndTypeInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/NullConstantInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/StringInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/StringInfo.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java diff --git a/group27/383117348/src/com/coderising/jvm/constant/UTF8Info.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/constant/UTF8Info.java rename to group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..17e3b77754 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + +} diff --git a/group27/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java similarity index 76% rename from group27/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java rename to group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java index 2688ae5810..3a3e4dd7b9 100644 --- a/group27/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java @@ -48,4 +48,18 @@ private byte[] getByteBySize(int size){ } return by; } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = code[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } } diff --git a/group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader.java rename to group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java diff --git a/group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader_backup.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileLoader_backup.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader_backup.java rename to group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileLoader_backup.java diff --git a/group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java similarity index 92% rename from group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java rename to group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java index 209ee78d36..8a42fe4cb4 100644 --- a/group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java @@ -26,6 +26,7 @@ public ClassFile parse(byte[] codes) { if(!magicNum.equals("cafebabe")){ throw new RuntimeException("文件类型错误"); } + ByteCodeIterator iter = new ByteCodeIterator(codes); int minVersion = by.nextU2Int(); int majorVersion = by.nextU2Int(); @@ -34,14 +35,20 @@ public ClassFile parse(byte[] codes) { AccessFlag flag = parseAccessFlag(by); ClassIndex index = parseClassIndex(by); + parseInterfaces(iter); + file.setMinorVersion(minVersion); file.setMajorVersion(majorVersion); file.setAccessFlag(flag); file.setClassIndex(index); file.setConstPool(constant); + + return file; } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag flag = new AccessFlag(iter.nextU2Int()); return flag; @@ -105,6 +112,13 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { } return pool; } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2Int(); + + + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..e46b5885ab --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + return null; + + } +} diff --git a/group27/383117348/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java similarity index 71% rename from group27/383117348/src/com/coderising/jvm/test/ClassFileloaderTest.java rename to group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java index ff026ee819..fa5e910f98 100644 --- a/group27/383117348/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,5 +1,7 @@ package com.coderising.jvm.test; +import java.util.List; + import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -12,7 +14,9 @@ import com.coderising.jvm.constant.MethodRefInfo; import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; public class ClassFileloaderTest { @@ -193,6 +197,76 @@ public void testClassIndex(){ 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); + } } diff --git a/group27/383117348/src/com/coderising/jvm/test/EmployeeV1.java b/group27/383117348/mini-jvm/com/coderising/jvm/test/EmployeeV1.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/test/EmployeeV1.java rename to group27/383117348/mini-jvm/com/coderising/jvm/test/EmployeeV1.java diff --git a/group27/383117348/src/com/coderising/jvm/util/Util.java b/group27/383117348/mini-jvm/com/coderising/jvm/util/Util.java similarity index 100% rename from group27/383117348/src/com/coderising/jvm/util/Util.java rename to group27/383117348/mini-jvm/com/coderising/jvm/util/Util.java From 7adfa4e86575800dcaa83b5fb2239ed14e7ffbc5 Mon Sep 17 00:00:00 2001 From: Ren650119726 <102228177@qq.com> Date: Mon, 10 Apr 2017 15:18:38 +0800 Subject: [PATCH 008/151] =?UTF-8?q?=E7=AC=AC=E4=BA=94=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/coding/basic/stack/Stack.java | 38 ++++++++-- .../src/com/coding/basic/stack/StackUtil.java | 73 ++++++++++++++++++- .../com/coding/basic/stack/StackUtilTest.java | 44 +++++++++++ 3 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 group17/102228177/work4_09/src/com/coding/basic/stack/StackUtilTest.java diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java b/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java index 1af8fbfb7a..42b6362e2f 100644 --- a/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/Stack.java @@ -1,22 +1,48 @@ package com.coding.basic.stack; +import java.util.EmptyStackException; + public class Stack { - private ArrayList elementData = new ArrayList(); + private ArrayList elementData; + private int elementCount; - public void push(Object o){ + public Stack() { + this.elementData = new ArrayList(); + this.elementCount = 0; + } + public void push(Object o){ + elementData.add(o); + elementCount++; } public Object pop(){ - return null; + Object object = elementData.remove(elementCount-1); + elementCount--; + return object; } public Object peek(){ - return null; + if(isEmpty()){ + throw new EmptyStackException(); + } + return elementData.get(elementCount-1); } public boolean isEmpty(){ - return false; + return elementCount==0; } public int size(){ - return -1; + return elementCount; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < elementData.size(); i++) { + sb.append(elementData.get(i)).append(","); + } + sb = sb.deleteCharAt(sb.length()-1); + sb.append("]"); + return sb.toString(); } } \ No newline at end of file diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java index 2ecca1811c..5b8019e2b7 100644 --- a/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtil.java @@ -8,8 +8,22 @@ public class StackUtil { * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ public static void reverse(Stack s) { - + if(s.isEmpty()){ + return ; + } + int temp1 = (int) s.pop(); + reverse(s); + if(s.isEmpty()){ + s.push(temp1); + return ; + } + int temp2 = (int) s.pop(); + reverse(s); + s.push(temp1); + reverse(s); + s.push(temp2); } + /** * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 @@ -17,7 +31,19 @@ public static void reverse(Stack s) { * @param o */ public static void remove(Stack s,Object o) { - + if(s.isEmpty()){ + return ; + } + Stack stack = new Stack(); + while(!s.isEmpty()){ + Object pop = s.pop(); + if(!pop.equals(o)){ + stack.push(pop); + } + } + while(!stack.isEmpty()){ + s.push(stack.pop()); + } } /** @@ -27,7 +53,19 @@ public static void remove(Stack s,Object o) { * @return */ public static Object[] getTop(Stack s,int len) { - return null; + int i = 0; + Stack stack = new Stack(); + Object[] objects = new Object[len]; + while(i < len){ + Object o = s.pop(); + stack.push(o); + objects[i] = o; + i++; + } + while(!stack.isEmpty()){ + s.push(stack.pop()); + } + return objects; } /** * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz @@ -38,6 +76,35 @@ public static Object[] getTop(Stack s,int len) { * @return */ public static boolean isValidPairs(String s){ + Stack stack = new Stack(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '(': + case '[': + case '{': + stack.push(c); + break; + case ')': + if((char)stack.pop()!='('){ + return false; + } + break; + case ']': + if((char)stack.pop()!='['){ + return false; + } + break; + case '}': + if((char)stack.pop()!='{'){ + return false; + } + break; + } + } + if(stack.isEmpty()){ + return true; + } return false; } diff --git a/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtilTest.java b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..722dd25846 --- /dev/null +++ b/group17/102228177/work4_09/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,44 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class StackUtilTest { + Stack stack ; + { + stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + } + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReverse() { + StackUtil.reverse(stack); + Assert.assertEquals("[5,4,3,2,1]", stack.toString()); + } + @Test + public void testRemove() { + StackUtil.remove(stack, 3); + Assert.assertEquals("[1,2,4,5]", stack.toString()); + } + @Test + public void testGetTop(){ + Assert.assertEquals(new Object[]{5,4}, StackUtil.getTop(stack, 2)); + Assert.assertEquals("[1,2,3,4,5]", stack.toString()); + } +} From 14b90bcd79c5479a0fd663dce1e14e66dc4f6714 Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Mon, 10 Apr 2017 18:52:40 +0800 Subject: [PATCH 009/151] homework of 17/4/5 first commit ,read constantpool --- .../coderising/jvm/attr/AttributeInfo.java | 18 +++ .../com/coderising/jvm/attr/CodeAttr.java | 10 ++ .../com/coderising/jvm/clz/AccessFlag.java | 24 ++++ .../com/coderising/jvm/clz/ClassFile.java | 76 ++++++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 +++ .../coderising/jvm/constant/ClassInfo.java | 26 ++++ .../coderising/jvm/constant/ConstantInfo.java | 32 +++++ .../coderising/jvm/constant/ConstantPool.java | 29 ++++ .../coderising/jvm/constant/DoubleInfo.java | 10 ++ .../coderising/jvm/constant/FieldRefInfo.java | 52 +++++++ .../coderising/jvm/constant/FloatInfo.java | 10 ++ .../coderising/jvm/constant/IntegerInfo.java | 20 +++ .../com/coderising/jvm/constant/LongInfo.java | 10 ++ .../jvm/constant/MethodRefInfo.java | 52 +++++++ .../jvm/constant/NameAndTypeInfo.java | 43 ++++++ .../jvm/constant/NullConstantInfo.java | 10 ++ .../coderising/jvm/constant/StringInfo.java | 25 ++++ .../com/coderising/jvm/constant/UTF8Info.java | 31 +++++ .../java/com/coderising/jvm/field/Field.java | 51 +++++++ .../jvm/loader/ByteCodeIterator.java | 41 ++++++ .../jvm/loader/ClassFileLoader.java | 5 - .../jvm/loader/ClassFileParser.java | 130 ++++++++++++++++++ .../com/coderising/jvm/method/Method.java | 27 ++++ .../java/com/coderising/jvm/util/Util.java | 21 +++ .../com/coding/basic/{ => stack}/Stack.java | 4 +- .../com/coding/basic/stack/StackUtil.java | 47 +++++++ .../coding/basic/stack/expr/InfixExpr.java | 14 ++ .../com/coding/basic/stack/StackUtilTest.java | 65 +++++++++ .../basic/stack/expr/InfixExprTest.java | 35 +++++ 29 files changed, 931 insertions(+), 6 deletions(-) create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/AccessFlag.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassIndex.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java rename group17/82427129/JavaUtil/src/main/java/com/coding/basic/{ => stack}/Stack.java (88%) create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java create mode 100644 group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/StackUtilTest.java create mode 100644 group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..11e25039c3 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,18 @@ +package com.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/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..bdf080d421 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.attr; + +public class CodeAttr extends AttributeInfo{ + + public CodeAttr(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + // TODO Auto-generated constructor stub + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/AccessFlag.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..ee70c4305c --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..d1d3b4159d --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,76 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public int getMinorVersion() { + return minorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + public int getMajorVersion() { + return majorVersion; + } + + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ClassIndex getClzIndex() { + return clzIndex; + } + + public void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public List getFields() { + return fields; + } + + public void addFields(Field f){ + this.fields.add(f); + } + + public List getMethods() { + return methods; + } + + public void addMethods(Method m){ + this.methods.add(m); + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassIndex.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..7750d4439d --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c0d67993ed --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = CLASS_INFO;// u1 tag + private int name_index;// u2 name_index + + @Override + public int getType() { + return type; + } + + public int getName_index() { + return name_index; + } + + public void setName_index(int name_index) { + this.name_index = name_index; + } + + public String getClassName() { + int name_index = getName_index(); + UTF8Info utf8 = (UTF8Info) this.constantPool + .getConstantInfo(name_index); + return utf8.getValue(); + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..885fba98b5 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int INTEGER_INFO = 3; + public static final int FLOAT_INFO = 4; + public static final int LONG_INFO = 5; + public static final int DOUBLE_INFO = 6; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + + protected ConstantPool constantPool; + + public ConstantInfo() {} + + public ConstantInfo(ConstantPool cp){ + this.constantPool = cp; + } + + public abstract int getType(); + + public ConstantPool getConstantPool(){ + return this.constantPool; + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..179b5ad9bf --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + private List cl = new ArrayList(); + private int constant_pool_size; + + public int getConstant_pool_size() { + return constant_pool_size; + } + + public void setConstant_pool_size(int constant_pool_size) { + this.constant_pool_size = constant_pool_size; + } + + public void addConstantInfo(ConstantInfo e){ + cl.add(e); + } + + public ConstantInfo getConstantInfo(int index) { + return cl.get(index); + } + + public int getSize() { + return cl.size() - 1;// 减去常量池的长度一项 + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java new file mode 100644 index 0000000000..9d6112ee35 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.constant; + +public class DoubleInfo extends ConstantInfo { + private int type = DOUBLE_INFO; + + @Override + public int getType() { + return type; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..8d3a8c25c8 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo { + private int type = FIELD_INFO;//u1 tag + private int class_index;//u2 class_index + private int name_and_type_index;//u2 name_and_type_index + + @Override + public int getType() { + return type; + } + + public int getClass_index() { + return class_index; + } + + public void setClass_index(int class_index) { + this.class_index = class_index; + } + + public int getName_and_type_index() { + return name_and_type_index; + } + + public void setName_and_type_index(int name_and_type_index) { + this.name_and_type_index = name_and_type_index; + } + + @Override + public String toString() { + return getClassName() + ":"+getFieldName()+" : "+getFieldType(); + } + + public String getClassName() { + ClassInfo classInfo = (ClassInfo) this.constantPool + .getConstantInfo(class_index); + return classInfo.getClassName(); + } + + public String getFieldName() { + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) this.constantPool + .getConstantInfo(name_and_type_index); + return nameAndTypeInfo.getName(); + } + + public String getFieldType() { + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) this.constantPool + .getConstantInfo(name_and_type_index); + return nameAndTypeInfo.getTypeInfo(); + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java new file mode 100644 index 0000000000..d02f37f6d8 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.constant; + +public class FloatInfo extends ConstantInfo { + private int type = FLOAT_INFO; + + @Override + public int getType() { + return type; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java new file mode 100644 index 0000000000..b89a8925c4 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java @@ -0,0 +1,20 @@ +package com.coderising.jvm.constant; + +public class IntegerInfo extends ConstantInfo { + private int type = INTEGER_INFO; + private int Num; + + @Override + public int getType() { + return type; + } + + public int getNum() { + return Num; + } + + public void setNum(int num) { + Num = num; + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java new file mode 100644 index 0000000000..23c80a2640 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.constant; + +public class LongInfo extends ConstantInfo { + private int type = LONG_INFO; + + @Override + public int getType() { + return type; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..86a199808b --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + private int type = METHOD_INFO;//u1 tag + private int class_index;//u2 class_index + private int name_and_type_index;//u2 name_and_type_index + + @Override + public int getType() { + return type; + } + + public int getClass_index() { + return class_index; + } + + public void setClass_index(int class_index) { + this.class_index = class_index; + } + + public int getName_and_type_index() { + return name_and_type_index; + } + + public void setName_and_type_index(int name_and_type_index) { + this.name_and_type_index = name_and_type_index; + } + + public String getClassName() { + ClassInfo c = (ClassInfo) this.constantPool + .getConstantInfo(class_index); + return c.getClassName(); + } + + public String getMethodName() { + NameAndTypeInfo nt = (NameAndTypeInfo) this.constantPool + .getConstantInfo(name_and_type_index); + return nt.getName(); + } + + public String getParamsAndReturnType() { + NameAndTypeInfo nt = (NameAndTypeInfo) this.constantPool + .getConstantInfo(name_and_type_index); + return nt.getTypeInfo(); + } + + @Override + public String toString() { + return getClassName() + ":" + getMethodName() + ":" + + getParamsAndReturnType(); + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..61b434d245 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,43 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo { + private int type = NAME_AND_TYPE_INFO;// u1 tag + private int name_index;//u2 name_index + private int descriptor_index;//u2 descriptor_index + + @Override + public int getType() { + return type; + } + + public int getName_index() { + return name_index; + } + + public void setName_index(int name_index) { + this.name_index = name_index; + } + + public int getDescriptor_index() { + return descriptor_index; + } + + public void setDescriptor_index(int descriptor_index) { + this.descriptor_index = descriptor_index; + } + + public String getName() { + UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(name_index); + return u.getValue(); + } + + public String getTypeInfo() { + UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(descriptor_index); + return u.getValue(); + } + + @Override + public String toString() { + return "(" + getName() + "," + getTypeInfo() + ")"; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..b383988fe7 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo{ + + @Override + public int getType() { + return -1; + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..b2bbbe9093 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo { + private int type = STRING_INFO;//u1 tag + private int string_index;//u2 string_index + @Override + public int getType() { + return type; + } + public int getString_index() { + return string_index; + } + public void setString_index(int string_index) { + this.string_index = string_index; + } + public String getString(){ + UTF8Info u = (UTF8Info)this.constantPool.getConstantInfo(string_index); + return u.getValue(); + } + @Override + public String toString() { + return getString(); + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..4bcf998504 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo { + private int type = UTF8_INFO;//u1 tag + private int length;//u2 length + private String value;//n 个 u1 + public UTF8Info(ConstantPool pool) { + super(pool); + } + @Override + public int getType() { + return type; + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public String toString() { + return "UTF8Info [type="+type+",length="+length+",value="+value+"]"; + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..19fcec9e46 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag;//u2 access_flags + private int nameIndex;//u2 name_index + private int descriptorIndex;//u2 descriptor_index + //attr 属性表信息首次写jvm先放弃,以后再加 + + 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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + + public int getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..7bd30d2832 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + private byte[] codes; + private int pos = 0; + + public void back(int length) { + if (pos - length < 0) { + throw new RuntimeException("back length is too long:" + length + + ",pos:" + pos); + } + pos -= length; + } + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public int nextU1toInt() { + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2toInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4toInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], + codes[pos++], codes[pos++] }); + } + + public String nextUxtoHexString(int len) { + byte[] bytes = new byte[len]; + for (int i = 0; i < len; i++) { + bytes[i] = codes[pos++]; + } + return Util.byteToHexString(bytes); + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java index fafac43407..d8818219ed 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -96,9 +96,4 @@ private String convertName(String className) { return sb.toString(); } - public static void main(String[] args) { - String d = "com.taiji.array.Load"; - ClassFileLoader cc = new ClassFileLoader(); - System.out.print(cc.convertName(d)); - } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..888dfe4817 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ClassFileParser { + /** + * 读取ClassFile对象 + * @param codes + * @return + */ + public ClassFile parse(byte[] codes) { + ClassFile cf = new ClassFile(); + ByteCodeIterator itr = new ByteCodeIterator(codes); + String magicNumber = itr.nextUxtoHexString(4);//1读取魔数 + if (!magicNumber.equals("cafebabe")) { + throw new RuntimeException("magicNum not ok"); + } + cf.setMajorVersion(itr.nextU2toInt());//2读取主版本号 + cf.setMinorVersion(itr.nextU2toInt());//3读取次版本号 + + ConstantPool pool = parseConstantPool(itr);//4、5读取常量池 + cf.setPool(pool); + + cf.setAccessFlag(new AccessFlag(itr.nextU2toInt()));//6读取访问标志 + + ClassIndex classIndex = parseClassIndex(itr);//读取类引用7this和8super + cf.setClzIndex(classIndex); + + return cf; + } + + /** + * 读取this super对象引用 + * @param itr + * @return + */ + public ClassIndex parseClassIndex(ByteCodeIterator itr) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(itr.nextU2toInt()); + classIndex.setSuperClassIndex(itr.nextU2toInt()); + return classIndex; + } + /** + * 读取常量池 + * @param itr + * @return + */ + public ConstantPool parseConstantPool(ByteCodeIterator itr) { + int count = itr.nextU2toInt(); + ConstantPool pool = new ConstantPool(); + pool.setConstant_pool_size(count); + pool.addConstantInfo(new NullConstantInfo());// 占住常量池的第一个,常量池是的index从1开始 + + for (int i = 1; i < count; i++) { + int tag = itr.nextU1toInt(); + switch (tag) { + case ConstantInfo.CLASS_INFO: + ClassInfo classInfo = new ClassInfo(); + classInfo.setName_index(itr.nextU2toInt()); + pool.addConstantInfo(classInfo); + break; + + case ConstantInfo.UTF8_INFO: + UTF8Info utf8Info = new UTF8Info(pool); + int length = itr.nextU2toInt(); + String value = itr.nextUxtoHexString(length); + utf8Info.setLength(length); + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + break; + + case ConstantInfo.STRING_INFO: + StringInfo si = new StringInfo(); + si.setString_index(itr.nextU2toInt()); + pool.addConstantInfo(si); + break; + + case ConstantInfo.NAME_AND_TYPE_INFO: + NameAndTypeInfo nt = new NameAndTypeInfo(); + nt.setName_index(itr.nextU2toInt()); + nt.setDescriptor_index(itr.nextU2toInt()); + pool.addConstantInfo(nt); + break; + + case ConstantInfo.METHOD_INFO: + MethodRefInfo m = new MethodRefInfo(); + m.setClass_index(itr.nextU2toInt()); + m.setName_and_type_index(itr.nextU2toInt()); + pool.addConstantInfo(m); + break; + + case ConstantInfo.FIELD_INFO: + FieldRefInfo f = new FieldRefInfo(); + f.setClass_index(itr.nextU2toInt()); + f.setName_and_type_index(itr.nextU2toInt()); + pool.addConstantInfo(f); + break; + + /*case ConstantInfo.FLOAT_INFO: + + break; + + case ConstantInfo.INTEGER_INFO: + break; + + case ConstantInfo.DOUBLE_INFO: + break; + + case ConstantInfo.LONG_INFO: + break;*/ + + default: + throw new RuntimeException("the constant pool tag " + tag + + " has not been implemented yet."); + } + } + return pool; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..8a876551a0 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.method; + +public class Method { + private int access_flags; + private int name_index; + private int type_index; + + + public int getAccess_flags() { + return access_flags; + } + public void setAccess_flags(int access_flags) { + this.access_flags = access_flags; + } + public int getName_index() { + return name_index; + } + public void setName_index(int name_index) { + this.name_index = name_index; + } + public int getType_index() { + return type_index; + } + public void setType_index(int type_index) { + this.type_index = type_index; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..2201593cd2 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + public static String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/Stack.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java similarity index 88% rename from group17/82427129/JavaUtil/src/main/java/com/coding/basic/Stack.java rename to group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java index 6bde3e3105..007362e95a 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/Stack.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java @@ -1,7 +1,9 @@ -package com.coding.basic; +package com.coding.basic.stack; import java.util.EmptyStackException; +import com.coding.basic.ArrayList; + public class Stack { private ArrayList elementData = new ArrayList(); diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..e1bc00858f --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,47 @@ +package com.coding.basic.stack; + +public class StackUtil { + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + + } + /** + * 添加元素到栈底部 + * @param s + * @param value + */ + public static void addToBottom(Stack s, Integer value){ + + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + + } + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + return null; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + return false; + } +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..cd086dfe79 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,14 @@ +package com.coding.basic.stack.expr; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + return 0.0f; + } +} diff --git a/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/StackUtilTest.java b/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..e47a5d44d4 --- /dev/null +++ b/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,65 @@ +package com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +public class StackUtilTest { + + @Test + public void testReverse() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testAddToBottom() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java b/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..4152869ad2 --- /dev/null +++ b/group17/82427129/JavaUtil/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,35 @@ +package com.coding.basic.stack.expr; + +import org.junit.Assert; +import org.junit.Test; + +public class InfixExprTest { + + @Test + public void testEvaluate() { + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + } + +} From 35f6dba078285f5d8fc93b8b397a2797cf05cc16 Mon Sep 17 00:00:00 2001 From: gongxun Date: Mon, 10 Apr 2017 23:26:44 +0800 Subject: [PATCH 010/151] template --- .../785396327/3.26/jvm_1/ClassFileLoader.java | 2 +- group17/785396327/4.5/clz/AccessFlag.java | 28 ++ group17/785396327/4.5/clz/ClassFile.java | 89 ++++++ group17/785396327/4.5/clz/ClassIndex.java | 25 ++ group17/785396327/4.5/constant/ClassInfo.java | 27 ++ .../785396327/4.5/constant/ConstantInfo.java | 31 ++ .../785396327/4.5/constant/ConstantPool.java | 31 ++ .../785396327/4.5/constant/FieldRefInfo.java | 57 ++++ .../785396327/4.5/constant/MethodRefInfo.java | 48 ++++ .../4.5/constant/NameAndTypeInfo.java | 48 ++++ .../4.5/constant/NullConstantInfo.java | 14 + .../785396327/4.5/constant/StringInfo.java | 29 ++ group17/785396327/4.5/constant/UTF8Info.java | 33 +++ .../4.5/test/ClassFileloaderTest.java | 265 ++++++++++++++++++ group17/785396327/4.5/util/Util.java | 27 ++ 15 files changed, 753 insertions(+), 1 deletion(-) create mode 100644 group17/785396327/4.5/clz/AccessFlag.java create mode 100644 group17/785396327/4.5/clz/ClassFile.java create mode 100644 group17/785396327/4.5/clz/ClassIndex.java create mode 100644 group17/785396327/4.5/constant/ClassInfo.java create mode 100644 group17/785396327/4.5/constant/ConstantInfo.java create mode 100644 group17/785396327/4.5/constant/ConstantPool.java create mode 100644 group17/785396327/4.5/constant/FieldRefInfo.java create mode 100644 group17/785396327/4.5/constant/MethodRefInfo.java create mode 100644 group17/785396327/4.5/constant/NameAndTypeInfo.java create mode 100644 group17/785396327/4.5/constant/NullConstantInfo.java create mode 100644 group17/785396327/4.5/constant/StringInfo.java create mode 100644 group17/785396327/4.5/constant/UTF8Info.java create mode 100644 group17/785396327/4.5/test/ClassFileloaderTest.java create mode 100644 group17/785396327/4.5/util/Util.java diff --git a/group17/785396327/3.26/jvm_1/ClassFileLoader.java b/group17/785396327/3.26/jvm_1/ClassFileLoader.java index 95f68a5a7f..9a937ba631 100644 --- a/group17/785396327/3.26/jvm_1/ClassFileLoader.java +++ b/group17/785396327/3.26/jvm_1/ClassFileLoader.java @@ -12,7 +12,7 @@ public class ClassFileLoader { public byte[] readBinaryCode(String className) { InputStream fis = null; - String filePath = clzPaths.get(0) + "\\\\" + className.replaceAll("\\.", "\\\\") + ".class"; + String filePath = clzPaths.get(0) + File.pathSeparator + className.replaceAll("\\.", File.pathSeparator) + ".class"; byte[] buffer = new byte[(int) new File(filePath).length()]; try { if (clzPaths.size() > 0 && className != null && !className.trim().equals("")) { diff --git a/group17/785396327/4.5/clz/AccessFlag.java b/group17/785396327/4.5/clz/AccessFlag.java new file mode 100644 index 0000000000..bbdf7c8818 --- /dev/null +++ b/group17/785396327/4.5/clz/AccessFlag.java @@ -0,0 +1,28 @@ +package clz; + +/** + * Created by IBM on 2017/4/10. + */ +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} diff --git a/group17/785396327/4.5/clz/ClassFile.java b/group17/785396327/4.5/clz/ClassFile.java new file mode 100644 index 0000000000..d4a8b8ed0c --- /dev/null +++ b/group17/785396327/4.5/clz/ClassFile.java @@ -0,0 +1,89 @@ +package clz; + +import constant.ClassInfo; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/10. + */ +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; +// private List fields = new ArrayList(); +// private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + +// 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group17/785396327/4.5/clz/ClassIndex.java b/group17/785396327/4.5/clz/ClassIndex.java new file mode 100644 index 0000000000..d0eb281a09 --- /dev/null +++ b/group17/785396327/4.5/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package clz; + +/** + * Created by IBM on 2017/4/10. + */ +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + + public int getSuperClassIndex() { + return superClassIndex; + } + + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} diff --git a/group17/785396327/4.5/constant/ClassInfo.java b/group17/785396327/4.5/constant/ClassInfo.java new file mode 100644 index 0000000000..1143ac1faa --- /dev/null +++ b/group17/785396327/4.5/constant/ClassInfo.java @@ -0,0 +1,27 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group17/785396327/4.5/constant/ConstantInfo.java b/group17/785396327/4.5/constant/ConstantInfo.java new file mode 100644 index 0000000000..8e6eaf72cf --- /dev/null +++ b/group17/785396327/4.5/constant/ConstantInfo.java @@ -0,0 +1,31 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } +} diff --git a/group17/785396327/4.5/constant/ConstantPool.java b/group17/785396327/4.5/constant/ConstantPool.java new file mode 100644 index 0000000000..b7b29bf115 --- /dev/null +++ b/group17/785396327/4.5/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by IBM on 2017/4/10. + */ +public class ConstantPool { + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group17/785396327/4.5/constant/FieldRefInfo.java b/group17/785396327/4.5/constant/FieldRefInfo.java new file mode 100644 index 0000000000..1e86db4134 --- /dev/null +++ b/group17/785396327/4.5/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group17/785396327/4.5/constant/MethodRefInfo.java b/group17/785396327/4.5/constant/MethodRefInfo.java new file mode 100644 index 0000000000..a3df142200 --- /dev/null +++ b/group17/785396327/4.5/constant/MethodRefInfo.java @@ -0,0 +1,48 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class MethodRefInfo extends ConstantInfo { + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getNameAndTypeIndex() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } +} diff --git a/group17/785396327/4.5/constant/NameAndTypeInfo.java b/group17/785396327/4.5/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..f59efe07c0 --- /dev/null +++ b/group17/785396327/4.5/constant/NameAndTypeInfo.java @@ -0,0 +1,48 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group17/785396327/4.5/constant/NullConstantInfo.java b/group17/785396327/4.5/constant/NullConstantInfo.java new file mode 100644 index 0000000000..c6bc0c17e5 --- /dev/null +++ b/group17/785396327/4.5/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class NullConstantInfo extends ConstantInfo { + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } +} diff --git a/group17/785396327/4.5/constant/StringInfo.java b/group17/785396327/4.5/constant/StringInfo.java new file mode 100644 index 0000000000..595eed7f47 --- /dev/null +++ b/group17/785396327/4.5/constant/StringInfo.java @@ -0,0 +1,29 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group17/785396327/4.5/constant/UTF8Info.java b/group17/785396327/4.5/constant/UTF8Info.java new file mode 100644 index 0000000000..12b8395559 --- /dev/null +++ b/group17/785396327/4.5/constant/UTF8Info.java @@ -0,0 +1,33 @@ +package constant; + +/** + * Created by IBM on 2017/4/10. + */ +public class UTF8Info extends ConstantInfo { + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..7c32811a45 --- /dev/null +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -0,0 +1,265 @@ +package test; + +import clz.ClassFile; +import constant.*; +import jvm_1.ClassFileLoader; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.lang.reflect.Method; + +/** + * Created by IBM on 2017/4/10. + */ +public class ClassFileloaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + +// clzFile = loader.loadClass(className); + clzFile.print(); + } + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + +// ClassIndex clzIndex = clzFile.getClzIndex(); +// ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); +// ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); +// +// +// 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); + } + +} diff --git a/group17/785396327/4.5/util/Util.java b/group17/785396327/4.5/util/Util.java new file mode 100644 index 0000000000..9bcb3c4e10 --- /dev/null +++ b/group17/785396327/4.5/util/Util.java @@ -0,0 +1,27 @@ +package util; + +/** + * Created by IBM on 2017/4/10. + */ +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i Date: Mon, 10 Apr 2017 23:53:14 +0800 Subject: [PATCH 011/151] test04 test05 --- group17/1158154002/.classpath | 2 + .../src/test04/loader/ClassFileLoader.java | 61 ++++++++++ .../test04/loader/ClassFileloaderTest.java | 84 +++++++++++++ .../src/test04/loader/EmployeeV1.java | 28 +++++ .../src/test04/lru/LRUPageFrame.java | 112 +++++++++++++++++ .../src/test04/lru/LRUPageFrameTest.java | 29 +++++ .../1158154002/src/test05/stack/Stack.java | 43 +++++++ .../src/test05/stack/StackTest.java | 52 ++++++++ .../src/test05/stack/StackUtil.java | 113 ++++++++++++++++++ 9 files changed, 524 insertions(+) create mode 100644 group17/1158154002/src/test04/loader/ClassFileLoader.java create mode 100644 group17/1158154002/src/test04/loader/ClassFileloaderTest.java create mode 100644 group17/1158154002/src/test04/loader/EmployeeV1.java create mode 100644 group17/1158154002/src/test04/lru/LRUPageFrame.java create mode 100644 group17/1158154002/src/test04/lru/LRUPageFrameTest.java create mode 100644 group17/1158154002/src/test05/stack/Stack.java create mode 100644 group17/1158154002/src/test05/stack/StackTest.java create mode 100644 group17/1158154002/src/test05/stack/StackUtil.java diff --git a/group17/1158154002/.classpath b/group17/1158154002/.classpath index 2d7497573f..44f39c3ace 100644 --- a/group17/1158154002/.classpath +++ b/group17/1158154002/.classpath @@ -3,5 +3,7 @@ + + diff --git a/group17/1158154002/src/test04/loader/ClassFileLoader.java b/group17/1158154002/src/test04/loader/ClassFileLoader.java new file mode 100644 index 0000000000..0f144fbb43 --- /dev/null +++ b/group17/1158154002/src/test04/loader/ClassFileLoader.java @@ -0,0 +1,61 @@ +package test04.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + + +public class ClassFileLoader { + private List clzPaths = new ArrayList(); + + + public byte[] readBinaryCode(String className) { + className=className.replace(".", File.separator)+".class"; + for (String path : clzPaths) { + String clzFileName=path+File.separator+className; + byte[] codes=loadClassFile(clzFileName); + if (codes!=null) { + return codes; + } + } + return null; + + + } + + private byte[] loadClassFile(String clzFileName) { + File file=new File(clzFileName); + try { + return IOUtils.toByteArray(new FileInputStream(file)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + } + + + + public void addClassPath(String path) { + if (this.clzPaths.contains(path)) { + return; + } + this.clzPaths.add(path); + } + + public String getClassPath_V1(){ + + return null; + } + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } +} diff --git a/group17/1158154002/src/test04/loader/ClassFileloaderTest.java b/group17/1158154002/src/test04/loader/ClassFileloaderTest.java new file mode 100644 index 0000000000..8897e72c91 --- /dev/null +++ b/group17/1158154002/src/test04/loader/ClassFileloaderTest.java @@ -0,0 +1,84 @@ +package test04.loader; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ClassFileloaderTest { + + static String path1 = "D:/mygit/coding2017/group17/1158154002/bin/"; + static String path2 = "file:/"; + + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + System.out.println(clzPath); + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "test04.loader.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1036, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "test04.loader.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + return elementData.remove(size()-1); + } + + public Object peek(){ + if (size()>0) { + return elementData.get(size()-1); + } else { + return null; + } + + } + + public boolean isEmpty(){ + return elementData.size()==0; + } + + public int size(){ + return elementData.size(); + } + + @Override + public String toString() { + StringBuffer sb=new StringBuffer(); + while (peek()!=null) { + sb.append(pop()).append(","); + } + + return sb.substring(0, sb.length()-1); + } + +} diff --git a/group17/1158154002/src/test05/stack/StackTest.java b/group17/1158154002/src/test05/stack/StackTest.java new file mode 100644 index 0000000000..b311650fff --- /dev/null +++ b/group17/1158154002/src/test05/stack/StackTest.java @@ -0,0 +1,52 @@ +package test05.stack; + +import java.util.Arrays; + +import org.junit.Test; + +public class StackTest { + @Test + public void testReverse(){ + Stack stack=new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + + StackUtil.reverse(stack); + System.out.println(stack.toString()); + } + + @Test + public void testRemove(){ + Stack stack=new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + + StackUtil.remove(stack,3); + System.out.println(stack.toString()); + } + //isValidPairs + @Test + public void testGetTop(){ + Stack stack=new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + + System.out.println(Arrays.toString(StackUtil.getTop(stack,6))); + System.out.println(stack.toString()); + } + + @Test + public void testIsValidPairs(){ + System.out.println(StackUtil.isValidPairs("([e{d}f])")); + System.out.println(StackUtil.isValidPairs("([b{x]y})")); + } +} diff --git a/group17/1158154002/src/test05/stack/StackUtil.java b/group17/1158154002/src/test05/stack/StackUtil.java new file mode 100644 index 0000000000..b999c82706 --- /dev/null +++ b/group17/1158154002/src/test05/stack/StackUtil.java @@ -0,0 +1,113 @@ +package test05.stack; + +public class StackUtil { + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack temp=new Stack(); + while (s.peek()!=null) { + temp.push(s.pop()); + } + Stack temp2=new Stack(); + while (temp.peek()!=null) { + temp2.push(temp.pop()); + } + while (temp2.peek()!=null) { + s.push(temp2.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + Stack temp=new Stack(); + while (s.peek()!=null) { + Object obj=s.pop(); + if (!obj.equals(o)) { + temp.push(obj); + } + } + while (temp.peek()!=null) { + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + * @throws Exception + */ + public static Object[] getTop(Stack s,int len) { + if (len<=s.size()) { + Stack temp=new Stack(); + Object[] result=new Object[len]; + for (int i = 0; i < s.size(); i++) { + Object o=s.pop(); + temp.push(o); + if (i= 0; i--) { + char c = s.charAt(i); + if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { + s2.push(c); + } + } + + for (int i = 0; i < s1.size() / 2; i++) { + char a = (char) s1.pop(); + char b = (char) s2.pop(); + if (a == '(' && b != ')') { + return false; + } else if (a == ')' && b != '(') { + return false; + } else if (a == '[' && b != ']') { + return false; + } else if (a == ']' && b != '[') { + return false; + } else if (a == '{' && b != '}') { + return false; + } else if (a == '}' && b != '{') { + return false; + } + } + + return true; + } + + +} From 2f81c812351ec13557105399e6b4bc69e1d0f843 Mon Sep 17 00:00:00 2001 From: liuxianan// <1264835468@qq.com> Date: Tue, 11 Apr 2017 10:49:29 +0800 Subject: [PATCH 012/151] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9null?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/1264835468/src/assignment0405/StackUtil.java | 5 ++++- group17/1264835468/src/assignment0405/StackUtilTest.java | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/group17/1264835468/src/assignment0405/StackUtil.java b/group17/1264835468/src/assignment0405/StackUtil.java index 7e5c717b4d..dcaf1992dd 100644 --- a/group17/1264835468/src/assignment0405/StackUtil.java +++ b/group17/1264835468/src/assignment0405/StackUtil.java @@ -2,6 +2,8 @@ import assignment.Stack; +import java.util.Objects; + /** * Created by Administrator on 2017/4/6. */ @@ -35,7 +37,8 @@ public static void remove(Stack s, Object o) { Stack stack2 = new Stack(); while (!s.isEmpty()) { Object top = s.pop(); - if (!top.equals(o)) { + //Objects.equals(null, null) == true + if (!Objects.equals(top, o)) { stack2.push(top); } } diff --git a/group17/1264835468/src/assignment0405/StackUtilTest.java b/group17/1264835468/src/assignment0405/StackUtilTest.java index 58be1302f6..d36a17c29d 100644 --- a/group17/1264835468/src/assignment0405/StackUtilTest.java +++ b/group17/1264835468/src/assignment0405/StackUtilTest.java @@ -17,6 +17,7 @@ public void reverse() throws Exception { Assert.assertEquals("1, 2, 3, 4", stack.toString()); StackUtil.reverse(stack); Assert.assertEquals("4, 3, 2, 1", stack.toString()); + } @@ -30,6 +31,11 @@ public void remove() throws Exception { Assert.assertEquals("5, 6, 5, 4, 3, 2, 0", stack.toString()); StackUtil.remove(stack, 5); Assert.assertEquals("6, 4, 3, 2, 0", stack.toString()); + pushAll(stack, null, 7, null); + Assert.assertEquals("null, 7, null, 6, 4, 3, 2, 0", stack.toString()); + StackUtil.remove(stack, null); + Assert.assertEquals("7, 6, 4, 3, 2, 0", stack.toString()); + } From eb0e92d598b246c600568f2b27ac13e3d6e4f5f2 Mon Sep 17 00:00:00 2001 From: liuxianan// <1264835468@qq.com> Date: Tue, 11 Apr 2017 10:51:29 +0800 Subject: [PATCH 013/151] =?UTF-8?q?=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/article/20170402-20170409.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170402-20170409.md b/group17/article/20170402-20170409.md index 3d45ad0516..931f26886d 100644 --- a/group17/article/20170402-20170409.md +++ b/group17/article/20170402-20170409.md @@ -26,7 +26,7 @@ 296910598 -1264835468 +1264835468 http://www.jianshu.com/p/686572a97fb3 516886559 From 10c1cc1ed0ffc01f589a4727795b7020a0c1debb Mon Sep 17 00:00:00 2001 From: Ren650119726 <102228177@qq.com> Date: Tue, 11 Apr 2017 13:55:07 +0800 Subject: [PATCH 014/151] =?UTF-8?q?=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/article/20170402-20170409.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170402-20170409.md b/group17/article/20170402-20170409.md index 3d45ad0516..adee3992f0 100644 --- a/group17/article/20170402-20170409.md +++ b/group17/article/20170402-20170409.md @@ -12,7 +12,7 @@ 1204187480 -102228177 +102228177 http://note.youdao.com/noteshare?id=4be7978218219daddfb0bb85182be12e 876385982 From 9ee3c363b4866cf63048b8447052c9e92cd4167a Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Tue, 11 Apr 2017 16:35:53 +0800 Subject: [PATCH 015/151] =?UTF-8?q?=E5=8A=A0=E4=BA=86=E4=BA=9B=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding/basic/stack/expr/InfixExpr.java | 174 +++++++++++++++++- 1 file changed, 170 insertions(+), 4 deletions(-) diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java index cc084db36d..4406d7d304 100644 --- a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixExpr.java @@ -1,15 +1,181 @@ package com.coding.basic.stack.expr; -public class InfixExpr { - String expr = null; +import java.util.ArrayList; + +import com.coding.basic.stack.Stack; +import com.coding.basic.stack.StackUtil; +public class InfixExpr { + private String expr = null; + public InfixExpr(String expr) { this.expr = expr; } - + /** + * 对expr进行解析计算 + * @return + */ public float evaluate() { + float f = 0.0f; + //如果不为空继续解析 + if (expr != null || expr.length() > 0) { + //如果符号不对称,抛出异常 + if (!StackUtil.isValidPairs(expr)) { + try { + throw new Exception("格式不正确,解析表达式失败!"); + } catch (Exception e) { + e.printStackTrace(); + } + }; + //将字符串转化为集合 + ArrayList list=getStringList(expr); + //根据获得的集合转化为后序表达式集合 + ArrayList postOrder = getPostOrder(list); + Stack stack = new Stack(); + for (int i = 0; i < postOrder.size(); i++) { + //如果为数字,则压入栈 + if(Character.isDigit(postOrder.get(i).charAt(0))){ + stack.push(Float.parseFloat(postOrder.get(i))); + }else{ + //否则,取出栈顶两个元素进行计算. + Float back = (Float)stack.pop(); + Float front = (Float)stack.pop(); + Float res = 0.0f; + switch (postOrder.get(i).charAt(0)) { + case '+': + res = front + back; + break; + case '-': + res = front - back; + break; + case '*': + res = front * back; + break; + case '/': + res = front / back; + break; + } + //将结果再压回栈中 + stack.push(res); + } + } + //最终计算结果出栈; + f = (Float)stack.pop(); - return 0.0f; + } else { + //为空抛出异常 + try { + throw new Exception("表达式内容为空,解析失败!"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return f; + } + /** + * 将字符串转换为集合方法 + * @param str + * @return + */ + private ArrayList getStringList(String str) { + ArrayList result = new ArrayList(); + String num = ""; + for (int i = 0; i < str.length(); i++) { + //如果为数字,叠加到num字符串中 + if (Character.isDigit(str.charAt(i))) { + num = num + str.charAt(i); + } else { + //如果num不为空,表示数字字符凑够了,加到集合里 + if (num != "") { + result.add(num); + } + //然后再把非数字字符也加到集合中,清空num字符串 + result.add(str.charAt(i) + ""); + num = ""; + } + } + //最后判断下,num中还有值没,有的话加到集合里 + if (num != "") { + result.add(num); + } + //返回结果 + return result; } + + /** + * 中序表达式转后序表达式 + * @param list + * @return + */ + private ArrayList getPostOrder(ArrayList list) { + ArrayList result = new ArrayList(); + Stack stack = new Stack(); + for (int i = 0; i < list.size(); i++) { + //如果为数字,加到集合里 + if (Character.isDigit(list.get(i).charAt(0))) { + result.add(list.get(i)); + } else { + switch (list.get(i).charAt(0)) { + //如果有左括号,先压入操作符栈中 + case '(': + stack.push(list.get(i)); + break; + //ok,等到右括号了 + case ')': + //先看看操作符栈顶是不是左括号头头 + while (!stack.peek().equals("(")) { + //不是左括号头头,就把操作符栈中的操作符弹出来一个,加到集合里,一直弹到见到左括号为止 + result.add((String) stack.pop()); + } + //最后把左括号也弹出来,这样就只有加减乘除没有括号了 + stack.pop(); + break; + default: + //这里全是处理加减乘除的操作 + //如果操作符栈不为空,比较下当前操作符和操作符栈顶的操作符优先级大小 + while (!stack.isEmpty() && compare((String) stack.peek(), list.get(i))) { + //如果栈顶操作符优先级大于当前,则栈中的操作符弹出加到集合里 + result.add((String) stack.pop()); + } + //否则继续压到栈中,或者之前栈中元素已经弹出,再将优先级小的操作符加到操作符栈中. + stack.push(list.get(i)); + break; + } + } + } + while (!stack.isEmpty()) { + //最后看下操作符栈还有操作符没,有了加到集合末尾 + result.add((String) stack.pop()); + } + return result; + } + /** + * 操作符优先级比较算法 + * @param peek + * @param cur + * @return + */ + public static boolean compare(String peek, String cur) { + //乘除优先级大于加减 + //如果操作符栈顶操作符的优先级大于当前操作符的优先级,则返回true + if ("*".equals(peek) && ("/".equals(cur) || "*".equals(cur) || "+".equals(cur) || "-".equals(cur))) { + return true; + } else if ("/".equals(peek) && ("/".equals(cur) || "*".equals(cur) || "+".equals(cur) || "-".equals(cur))) { + return true; + } else if ("+".equals(peek) && ("+".equals(cur) || "-".equals(cur))) { + return true; + } else if ("-".equals(peek) && ("+".equals(cur) || "-".equals(cur))) { + return true; + } + //如果当前操作符的优先级大于栈顶的操作符优先级,返回false + return false; + } + + public static void main(String[] args) { + InfixExpr expr = new InfixExpr("3*20+13*5-40/2"); + float f = expr.evaluate(); + System.out.println(f); + } } From e8142c7a1dcb45022b9b06bafa60915f9fa6ff19 Mon Sep 17 00:00:00 2001 From: gongxun Date: Tue, 11 Apr 2017 23:17:05 +0800 Subject: [PATCH 016/151] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../785396327/3.26/jvm_1/ClassFileLoader.java | 11 +- .../4.5/iterator/ByteCodeIterator.java | 40 ++++++ .../785396327/4.5/parse/ClassFilePaser.java | 50 +++++++ .../4.5/test/ClassFileloaderTest.java | 122 +++++++++--------- group17/785396327/4.5/util/Util.java | 3 + 5 files changed, 164 insertions(+), 62 deletions(-) create mode 100644 group17/785396327/4.5/iterator/ByteCodeIterator.java create mode 100644 group17/785396327/4.5/parse/ClassFilePaser.java diff --git a/group17/785396327/3.26/jvm_1/ClassFileLoader.java b/group17/785396327/3.26/jvm_1/ClassFileLoader.java index 9a937ba631..66f209f161 100644 --- a/group17/785396327/3.26/jvm_1/ClassFileLoader.java +++ b/group17/785396327/3.26/jvm_1/ClassFileLoader.java @@ -1,5 +1,8 @@ package jvm_1; +import clz.ClassFile; +import parse.ClassFilePaser; + import java.io.*; import java.util.ArrayList; import java.util.List; @@ -12,7 +15,7 @@ public class ClassFileLoader { public byte[] readBinaryCode(String className) { InputStream fis = null; - String filePath = clzPaths.get(0) + File.pathSeparator + className.replaceAll("\\.", File.pathSeparator) + ".class"; + String filePath = clzPaths.get(0) + "\\\\" + className.replaceAll("\\.", "\\\\") + ".class"; byte[] buffer = new byte[(int) new File(filePath).length()]; try { if (clzPaths.size() > 0 && className != null && !className.trim().equals("")) { @@ -47,4 +50,10 @@ public String getClassPath() { } return sb.substring(0, sb.length() - 1); } + + public ClassFile loadClass(String className) { + byte[] bytes = readBinaryCode(className); + ClassFilePaser classFilePaser = new ClassFilePaser(); + return classFilePaser.parse(bytes); + } } diff --git a/group17/785396327/4.5/iterator/ByteCodeIterator.java b/group17/785396327/4.5/iterator/ByteCodeIterator.java new file mode 100644 index 0000000000..7157d01a2c --- /dev/null +++ b/group17/785396327/4.5/iterator/ByteCodeIterator.java @@ -0,0 +1,40 @@ +package iterator; + +import util.Util; + +import java.util.Arrays; + +/** + * Created by IBM on 2017/4/11. + */ +public class ByteCodeIterator { + + byte[] codes; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public String nextU4ToHexString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 4; i++) { + byte code = codes[i]; + int value = code & 0xff; + sb.append(Integer.toHexString(value)); + } + codes = Arrays.copyOfRange(codes, 4, codes.length); + return sb.toString(); + } + + public int nextU2ToInt() { + byte[] buff = new byte[]{codes[0], codes[1]}; + codes = Arrays.copyOfRange(codes, 2, codes.length); + return Util.byteToInt(buff); + } + + public int nextU1ToInt() { + byte[] buff = new byte[]{codes[0]}; + codes = Arrays.copyOfRange(codes, 1, codes.length); + return Util.byteToInt(buff); + } +} diff --git a/group17/785396327/4.5/parse/ClassFilePaser.java b/group17/785396327/4.5/parse/ClassFilePaser.java new file mode 100644 index 0000000000..3ddd9df6c3 --- /dev/null +++ b/group17/785396327/4.5/parse/ClassFilePaser.java @@ -0,0 +1,50 @@ +package parse; + +import clz.ClassFile; +import constant.ClassInfo; +import constant.ConstantInfo; +import constant.ConstantPool; +import constant.NullConstantInfo; +import iterator.ByteCodeIterator; + +/** + * Created by IBM on 2017/4/11. + */ +public class ClassFilePaser { + private ClassFile classFile; + + public ClassFile parse(byte[] codes) { + classFile = new ClassFile(); + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + String magic = iterator.nextU4ToHexString(); + if (!"cafebabe".equals(magic)) + return null; + + classFile.setMinorVersion(iterator.nextU2ToInt()); + classFile.setMajorVersion(iterator.nextU2ToInt()); + + ConstantPool constantPool = parseConstantPool(iterator); + classFile.setConstPool(constantPool); + + return classFile; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iterator) { + int poolSize = iterator.nextU2ToInt(); + System.out.println("constant pool size = " + (poolSize - 1)); + + ConstantPool constantPool = new ConstantPool(); + + constantPool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i < poolSize; i++) { + int tag = iterator.nextU1ToInt(); + if (tag == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(iterator.nextU2ToInt()); + constantPool.addConstantInfo(classInfo); + } + } + return constantPool; + } +} diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 7c32811a45..8c15346ca4 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -16,17 +16,17 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path1 = "D:\\workspace\\IDEA\\homework\\coding2017\\group17\\785396327\\out\\production\\785396327"; static String path2 = "C:\temp"; static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "jvm_1.EmployeeV1"; -// clzFile = loader.loadClass(className); - clzFile.print(); + clzFile = loader.loadClass(className); +// clzFile.print(); } @@ -57,12 +57,12 @@ public void testClassFileLength() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "jvm_1.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1056, byteCodes.length); + Assert.assertEquals(1020, byteCodes.length); } @@ -116,67 +116,67 @@ public void testConstantPool(){ ConstantPool pool = clzFile.getConstantPool(); - Assert.assertEquals(53, pool.getSize()); +// Assert.assertEquals(53, pool.getSize()); { ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); Assert.assertEquals(2, clzInfo.getUtf8Index()); - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); - Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); - } - { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); - Assert.assertEquals(4, clzInfo.getUtf8Index()); - - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); - Assert.assertEquals("java/lang/Object", utf8Info.getValue()); - } - { - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); - Assert.assertEquals("name", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(6); - Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(7); - Assert.assertEquals("age", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(8); - Assert.assertEquals("I", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(9); - Assert.assertEquals("", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(10); - Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(11); - Assert.assertEquals("Code", utf8Info.getValue()); - } - - { - MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); - Assert.assertEquals(3, methodRef.getClassInfoIndex()); - Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); - } - - { - NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); - Assert.assertEquals(9, nameAndType.getIndex1()); - Assert.assertEquals(14, nameAndType.getIndex2()); - } - //抽查几个吧 - { - MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); - Assert.assertEquals(1, methodRef.getClassInfoIndex()); - Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); - } - - { - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); - Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); +// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); +// Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); } +// { +// ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); +// Assert.assertEquals(4, clzInfo.getUtf8Index()); +// +// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); +// Assert.assertEquals("java/lang/Object", utf8Info.getValue()); +// } +// { +// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); +// Assert.assertEquals("name", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(6); +// Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(7); +// Assert.assertEquals("age", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(8); +// Assert.assertEquals("I", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(9); +// Assert.assertEquals("", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(10); +// Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(11); +// Assert.assertEquals("Code", utf8Info.getValue()); +// } +// +// { +// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); +// Assert.assertEquals(3, methodRef.getClassInfoIndex()); +// Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); +// } +// +// { +// NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); +// Assert.assertEquals(9, nameAndType.getIndex1()); +// Assert.assertEquals(14, nameAndType.getIndex2()); +// } +// //抽查几个吧 +// { +// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); +// Assert.assertEquals(1, methodRef.getClassInfoIndex()); +// Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); +// } +// +// { +// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); +// Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); +// } } @Test public void testClassIndex(){ diff --git a/group17/785396327/4.5/util/Util.java b/group17/785396327/4.5/util/Util.java index 9bcb3c4e10..f2e2b3d859 100644 --- a/group17/785396327/4.5/util/Util.java +++ b/group17/785396327/4.5/util/Util.java @@ -1,5 +1,7 @@ package util; +import constant.ConstantPool; + /** * Created by IBM on 2017/4/10. */ @@ -24,4 +26,5 @@ public static String byteToHexString(byte[] codes ){ } return buffer.toString(); } + } From bfa4908bcb67666705e24f9bc921e209b20897ee Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Wed, 12 Apr 2017 18:33:19 +0800 Subject: [PATCH 017/151] homeword test Past codes . --- .../com/coderising/jvm/attr/CodeAttr.java | 4 + .../com/coderising/jvm/clz/ClassFile.java | 28 ++- .../coderising/jvm/constant/ClassInfo.java | 12 +- .../coderising/jvm/constant/ConstantPool.java | 24 ++- .../jvm/constant/MethodRefInfo.java | 26 +-- .../jvm/loader/ClassFileLoader.java | 29 ++- .../jvm/loader/ClassFileParser.java | 27 ++- .../com/coderising/jvm/method/Method.java | 48 +++-- .../jvm/loader/ClassFileLoaderTest.java | 180 ++++++++++++++++++ 9 files changed, 329 insertions(+), 49 deletions(-) diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java index bdf080d421..a05fb3c27f 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java @@ -2,6 +2,10 @@ public class CodeAttr extends AttributeInfo{ + private String code; + public String getCode() { + return code; + } public CodeAttr(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); // TODO Auto-generated constructor stub diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java index d1d3b4159d..fee1cc2415 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; @@ -17,6 +18,31 @@ public class ClassFile { private List fields = new ArrayList(); private List methods = new ArrayList(); + 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()); + + } + + public String getClassName(){ + int index = this.clzIndex.getThisClassIndex(); + ClassInfo c = (ClassInfo)pool.getConstantInfo(index); + return c.getClassName(); + } + public String getSuperClassName(){ + int index = this.clzIndex.getSuperClassIndex(); + ClassInfo c = (ClassInfo)pool.getConstantInfo(index); + return c.getClassName(); + } + /* + * getter setter + * + */ public int getMinorVersion() { return minorVersion; } @@ -49,7 +75,7 @@ public void setClzIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - public ConstantPool getPool() { + public ConstantPool getConstantPool() { return pool; } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java index c0d67993ed..772ec3f1e0 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java @@ -2,23 +2,23 @@ public class ClassInfo extends ConstantInfo { private int type = CLASS_INFO;// u1 tag - private int name_index;// u2 name_index + private int utf8Index;// u2 name_index @Override public int getType() { return type; } - public int getName_index() { - return name_index; + public int getUtf8Index() { + return utf8Index; } - public void setName_index(int name_index) { - this.name_index = name_index; + public void setUtf8Index(int name_index) { + this.utf8Index = name_index; } public String getClassName() { - int name_index = getName_index(); + int name_index = getUtf8Index(); UTF8Info utf8 = (UTF8Info) this.constantPool .getConstantInfo(name_index); return utf8.getValue(); diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java index 179b5ad9bf..009b2c45c4 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java @@ -5,16 +5,8 @@ public class ConstantPool { private List cl = new ArrayList(); - private int constant_pool_size; + private int constantPoolSize; - public int getConstant_pool_size() { - return constant_pool_size; - } - - public void setConstant_pool_size(int constant_pool_size) { - this.constant_pool_size = constant_pool_size; - } - public void addConstantInfo(ConstantInfo e){ cl.add(e); } @@ -26,4 +18,18 @@ public ConstantInfo getConstantInfo(int index) { public int getSize() { return cl.size() - 1;// 减去常量池的长度一项 } + /* + * getter setter + */ + public int getConstantPoolSize() { + return constantPoolSize; + } + + public void setConstantPoolSize(int constantPoolSize) { + this.constantPoolSize = constantPoolSize; + } + + public String getUTF8String(int nameIndex) { + return ((UTF8Info)getConstantInfo(nameIndex)).getValue(); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java index 86a199808b..4064e09b39 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java @@ -2,45 +2,45 @@ public class MethodRefInfo extends ConstantInfo { private int type = METHOD_INFO;//u1 tag - private int class_index;//u2 class_index - private int name_and_type_index;//u2 name_and_type_index + private int classInfoIndex;//u2 class_index + private int nameAndTypeIndex;//u2 name_and_type_index @Override public int getType() { return type; } - public int getClass_index() { - return class_index; + public int getClassInfoIndex() { + return classInfoIndex; } - public void setClass_index(int class_index) { - this.class_index = class_index; + public void setClassInfoIndex(int class_index) { + this.classInfoIndex = class_index; } - public int getName_and_type_index() { - return name_and_type_index; + public int getNameAndTypeIndex() { + return nameAndTypeIndex; } - public void setName_and_type_index(int name_and_type_index) { - this.name_and_type_index = name_and_type_index; + public void setNameAndTypeIndex(int name_and_type_index) { + this.nameAndTypeIndex = name_and_type_index; } public String getClassName() { ClassInfo c = (ClassInfo) this.constantPool - .getConstantInfo(class_index); + .getConstantInfo(classInfoIndex); return c.getClassName(); } public String getMethodName() { NameAndTypeInfo nt = (NameAndTypeInfo) this.constantPool - .getConstantInfo(name_and_type_index); + .getConstantInfo(nameAndTypeIndex); return nt.getName(); } public String getParamsAndReturnType() { NameAndTypeInfo nt = (NameAndTypeInfo) this.constantPool - .getConstantInfo(name_and_type_index); + .getConstantInfo(nameAndTypeIndex); return nt.getTypeInfo(); } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java index d8818219ed..0c02adef66 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -8,10 +8,29 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.clz.ClassFile; + public class ClassFileLoader { private static final int BUFFERSIZE = 1024; private List clzPaths = new ArrayList(); + /** + * 装载class文件 + * 读取二进制字节流,并解析成ClassFile对象 + * @param className + * @return ClassFile + */ + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + /** + * 从.class文件读取二进制字节流 + * @param className + * @return + */ public byte[] readBinaryCode(String className) { if (clzPaths.size()<=0){ return null; @@ -36,7 +55,7 @@ public byte[] readBinaryCode(String className) { /** * 文件读取二进制字节流 * @param f - * @return + * @return byte[] * @throws FileNotFoundException */ private byte[] readFile(File f) throws FileNotFoundException { @@ -63,10 +82,18 @@ private byte[] readFile(File f) throws FileNotFoundException { return baos.toByteArray(); } + /** + * 增加类加载路径,加载时按增加时的先后顺序加载 + * @param path + */ public void addClassPath(String path) { clzPaths.add(path); } + /** + * 获取类加载路径 + * @return + */ public String getClassPath() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < clzPaths.size(); i++) { diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java index 888dfe4817..87f748c2d0 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java @@ -12,6 +12,7 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; public class ClassFileParser { /** @@ -59,7 +60,7 @@ public ClassIndex parseClassIndex(ByteCodeIterator itr) { public ConstantPool parseConstantPool(ByteCodeIterator itr) { int count = itr.nextU2toInt(); ConstantPool pool = new ConstantPool(); - pool.setConstant_pool_size(count); + pool.setConstantPoolSize(count);; pool.addConstantInfo(new NullConstantInfo());// 占住常量池的第一个,常量池是的index从1开始 for (int i = 1; i < count; i++) { @@ -67,7 +68,7 @@ public ConstantPool parseConstantPool(ByteCodeIterator itr) { switch (tag) { case ConstantInfo.CLASS_INFO: ClassInfo classInfo = new ClassInfo(); - classInfo.setName_index(itr.nextU2toInt()); + classInfo.setUtf8Index(itr.nextU2toInt()); pool.addConstantInfo(classInfo); break; @@ -95,8 +96,8 @@ public ConstantPool parseConstantPool(ByteCodeIterator itr) { case ConstantInfo.METHOD_INFO: MethodRefInfo m = new MethodRefInfo(); - m.setClass_index(itr.nextU2toInt()); - m.setName_and_type_index(itr.nextU2toInt()); + m.setClassInfoIndex(itr.nextU2toInt()); + m.setNameAndTypeIndex(itr.nextU2toInt()); pool.addConstantInfo(m); break; @@ -127,4 +128,22 @@ public ConstantPool parseConstantPool(ByteCodeIterator itr) { } return pool; } + /** + * 读取字段 + * @param itr + * @return + */ + public Field parseField(ByteCodeIterator itr){ + + return null; + } + /** + * 读取方法 + * @param itr + * @return + */ + public Field parseMethod(ByteCodeIterator itr){ + + return null; + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java index 8a876551a0..456e5d9f94 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java @@ -1,27 +1,45 @@ package com.coderising.jvm.method; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; + public class Method { - private int access_flags; - private int name_index; - private int type_index; + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private CodeAttr codeAttr; - public int getAccess_flags() { - return access_flags; + private ClassFile clzFile; + /* + * getter setter + */ + public int getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + public int getNameIndex() { + return nameIndex; } - public void setAccess_flags(int access_flags) { - this.access_flags = access_flags; + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; } - public int getName_index() { - return name_index; + public int getDescriptorIndex() { + return descriptorIndex; } - public void setName_index(int name_index) { - this.name_index = name_index; + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; } - public int getType_index() { - return type_index; + public CodeAttr getCodeAttr() { + return codeAttr; } - public void setType_index(int type_index) { - this.type_index = type_index; + public void setCodeAttr(CodeAttr codeAttr) { + this.codeAttr = codeAttr; } + public ClassFile getClzFile() { + return clzFile; + } + } diff --git a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java index e2ed056cc3..194db3cba0 100644 --- a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java +++ b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java @@ -1,13 +1,35 @@ package com.coderising.jvm.loader; +import java.util.List; + import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + public class ClassFileLoaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; static String path2 = "D:\\workProgram\\GitRepo\\coding2017\\group17\\82427129\\JavaUtil\\target\\classes"; + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path2); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + clzFile.print(); + } @Before public void setUp() throws Exception { } @@ -55,7 +77,93 @@ public void testMagicNumber(){ Assert.assertEquals("cafebabe", acctualValue); } + + @Test + public void testVersion(){ + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + } + + @Test + public void testConstantPool(){ + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getName_index()); + Assert.assertEquals(14, nameAndType.getDescriptor_index()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + private String byteToHexString(byte[] codes) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < codes.length; i++) { @@ -69,5 +177,77 @@ private String byteToHexString(byte[] codes) { } return buffer.toString(); } + + /** + * 下面是第三次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 17df039e0366f8f551d828fec668bcd41457067e Mon Sep 17 00:00:00 2001 From: gongxun Date: Wed, 12 Apr 2017 18:58:48 +0800 Subject: [PATCH 018/151] =?UTF-8?q?=E5=AE=8C=E6=88=90jvm=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E6=B1=A0=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../3.26/jvm_1/ClassFileloaderTest.java | 2 +- .../4.5/iterator/ByteCodeIterator.java | 10 ++ .../785396327/4.5/parse/ClassFilePaser.java | 53 ++++++- group17/785396327/4.5/stack/MyStack.java | 35 +++++ group17/785396327/4.5/stack/StackUtil.java | 115 +++++++++++++++ .../785396327/4.5/stack/StackUtilTest.java | 101 +++++++++++++ .../4.5/test/ClassFileloaderTest.java | 135 +++++++++--------- group17/785396327/4.5/util/Util.java | 2 - 8 files changed, 379 insertions(+), 74 deletions(-) create mode 100644 group17/785396327/4.5/stack/MyStack.java create mode 100644 group17/785396327/4.5/stack/StackUtil.java create mode 100644 group17/785396327/4.5/stack/StackUtilTest.java diff --git a/group17/785396327/3.26/jvm_1/ClassFileloaderTest.java b/group17/785396327/3.26/jvm_1/ClassFileloaderTest.java index 067cd93c2b..5a298da661 100644 --- a/group17/785396327/3.26/jvm_1/ClassFileloaderTest.java +++ b/group17/785396327/3.26/jvm_1/ClassFileloaderTest.java @@ -9,7 +9,7 @@ * Created by william on 2017/4/5. */ public class ClassFileloaderTest { - static String path1 = "D:\\workspace\\IDEA\\homework\\coding2017\\group17\\785396327\\out\\production\\785396327"; + static String path1 = "G:\\Git\\homework\\coding2017\\group17\\785396327\\3.12\\out\\production\\785396327"; static String path2 = "C:\temp"; diff --git a/group17/785396327/4.5/iterator/ByteCodeIterator.java b/group17/785396327/4.5/iterator/ByteCodeIterator.java index 7157d01a2c..904537b00d 100644 --- a/group17/785396327/4.5/iterator/ByteCodeIterator.java +++ b/group17/785396327/4.5/iterator/ByteCodeIterator.java @@ -1,5 +1,6 @@ package iterator; +import org.junit.Test; import util.Util; import java.util.Arrays; @@ -37,4 +38,13 @@ public int nextU1ToInt() { codes = Arrays.copyOfRange(codes, 1, codes.length); return Util.byteToInt(buff); } + + public byte[] nextLengthBytes(int length) { + byte[] result = new byte[length]; + for (int i = 0; i < length; i++) { + result[i] = codes[i]; + } + codes = Arrays.copyOfRange(codes, length, codes.length); + return result; + } } diff --git a/group17/785396327/4.5/parse/ClassFilePaser.java b/group17/785396327/4.5/parse/ClassFilePaser.java index 3ddd9df6c3..4e3053e78f 100644 --- a/group17/785396327/4.5/parse/ClassFilePaser.java +++ b/group17/785396327/4.5/parse/ClassFilePaser.java @@ -1,11 +1,12 @@ package parse; +import clz.AccessFlag; import clz.ClassFile; -import constant.ClassInfo; -import constant.ConstantInfo; -import constant.ConstantPool; -import constant.NullConstantInfo; +import clz.ClassIndex; +import com.sun.corba.se.impl.orbutil.closure.Constant; +import constant.*; import iterator.ByteCodeIterator; +import util.Util; /** * Created by IBM on 2017/4/11. @@ -27,9 +28,26 @@ public ClassFile parse(byte[] codes) { ConstantPool constantPool = parseConstantPool(iterator); classFile.setConstPool(constantPool); + AccessFlag accessFlag = parseAccessFlag(iterator); + classFile.setAccessFlag(accessFlag); + + ClassIndex classIndex = parseClassIndex(iterator); + classFile.setClassIndex(classIndex); return classFile; } + private ClassIndex parseClassIndex(ByteCodeIterator iterator) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iterator.nextU2ToInt()); + classIndex.setSuperClassIndex(iterator.nextU2ToInt()); + return classIndex; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iterator) { + AccessFlag accessFlag = new AccessFlag(iterator.nextU2ToInt()); + return accessFlag; + } + private ConstantPool parseConstantPool(ByteCodeIterator iterator) { int poolSize = iterator.nextU2ToInt(); System.out.println("constant pool size = " + (poolSize - 1)); @@ -43,6 +61,33 @@ private ConstantPool parseConstantPool(ByteCodeIterator iterator) { ClassInfo classInfo = new ClassInfo(constantPool); classInfo.setUtf8Index(iterator.nextU2ToInt()); constantPool.addConstantInfo(classInfo); + } else if (tag == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + constantPool.addConstantInfo(methodRefInfo); + } else if (tag == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + constantPool.addConstantInfo(fieldRefInfo); + } else if (tag == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(iterator.nextU2ToInt()); + constantPool.addConstantInfo(stringInfo); + } else if (tag == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(iterator.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iterator.nextU2ToInt()); + constantPool.addConstantInfo(nameAndTypeInfo); + } else if (tag == ConstantInfo.UTF8_INFO) { + UTF8Info utf8Info = new UTF8Info(constantPool); + int length = iterator.nextU2ToInt(); + utf8Info.setLength(length); + utf8Info.setValue(new String(iterator.nextLengthBytes(length))); + constantPool.addConstantInfo(utf8Info); + } else { + System.out.println("other class info "); } } return constantPool; diff --git a/group17/785396327/4.5/stack/MyStack.java b/group17/785396327/4.5/stack/MyStack.java new file mode 100644 index 0000000000..80ee0fdd62 --- /dev/null +++ b/group17/785396327/4.5/stack/MyStack.java @@ -0,0 +1,35 @@ +package stack; + +import java.util.ArrayList; + +/** + * Created by gongxun on 2017/4/12. + */ +public class MyStack { + private ArrayList elementData = new ArrayList(); + + public void push(T o) { + elementData.add(0, o); + } + + public T pop() { + return elementData.remove(0); + } + + public T peek() { + return elementData.get(0); + } + + public boolean isEmpty() { + return elementData.isEmpty(); + } + + public int size() { + return elementData.size(); + } + + @Override + public String toString() { + return elementData.toString(); + } +} diff --git a/group17/785396327/4.5/stack/StackUtil.java b/group17/785396327/4.5/stack/StackUtil.java new file mode 100644 index 0000000000..aa821a50ae --- /dev/null +++ b/group17/785396327/4.5/stack/StackUtil.java @@ -0,0 +1,115 @@ +package stack; + +/** + * Created by gongxun on 2017/4/12. + */ +public class StackUtil { + public static void bad_reverse(MyStack s) { + + } + + + public static void reverse_247565311(MyStack s) { + + } + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(MyStack s) { + MyStack tempStack = new MyStack(); + while (!s.isEmpty()) + addToBottom(tempStack, s.pop()); + while (!tempStack.isEmpty()) + s.push(tempStack.pop()); + } + + public static void addToBottom(MyStack s, Integer value) { + MyStack reserveStack = new MyStack(); + while (!s.isEmpty()) + reserveStack.push(s.pop()); + s.push(value); + while (!reserveStack.isEmpty()) + s.push(reserveStack.pop()); + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(MyStack s, Object o) { + if (null == o) + return; + MyStack tempStack = new MyStack(); + while (!s.isEmpty()) { + if (!s.peek().equals(o)) { + tempStack.push(s.pop()); + } else { + s.pop(); + break; + } + } + while (!tempStack.isEmpty()) + s.push(tempStack.pop()); + } + + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(MyStack s, int len) { + if (len > s.size()) + return null; + Object[] datas = new Object[len]; + for (int i = 0; i < len; i++) { + datas[i] = s.pop(); + } + return datas; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + if (s == null || s.trim().isEmpty()) + return false; + String[] arr = s.split(""); + MyStack stack = new MyStack(); + for (int i = 0; i < arr.length; i++) { + if ("(".equals(arr[i]) || "[".equals(arr[i]) || "{".equals(arr[i])) + stack.push(arr[i]); + if (")".equals(arr[i])) { + if (stack.peek().equals("(")) + stack.pop(); + else + return false; + } + if ("]".equals(arr[i])) { + if (stack.peek().equals("[")) + stack.pop(); + else + return false; + } + if ("}".equals(arr[i])) { + if (stack.peek().equals("{")) + stack.pop(); + else + return false; + } + } + return true; + } +} diff --git a/group17/785396327/4.5/stack/StackUtilTest.java b/group17/785396327/4.5/stack/StackUtilTest.java new file mode 100644 index 0000000000..bf411a953a --- /dev/null +++ b/group17/785396327/4.5/stack/StackUtilTest.java @@ -0,0 +1,101 @@ +package stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/12. + */ +public class StackUtilTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + /** + * [头元素,...,尾元素] + */ + @Test + public void testStack() { + MyStack stack = new MyStack(); + stack.push(1); + stack.push(2); + System.out.println(stack); + } + + @Test + public void testAddToBottom() { + MyStack s = new MyStack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[3, 2, 1, 0]", s.toString()); + + } + + @Test + public void testReverse() { + MyStack s = new MyStack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + } + + @Test + public void testReverse_247565311() { + MyStack s = new MyStack(); + s.push(1); + s.push(2); + s.push(3); + + Assert.assertEquals("[1, 2, 3]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + MyStack s = new MyStack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[3, 1]", s.toString()); + } + + @Test + public void testGetTop() { + MyStack s = new MyStack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 8c15346ca4..9f76c4ccbc 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -1,6 +1,7 @@ package test; import clz.ClassFile; +import clz.ClassIndex; import constant.*; import jvm_1.ClassFileLoader; import org.junit.After; @@ -14,9 +15,9 @@ * Created by IBM on 2017/4/10. */ public class ClassFileloaderTest { - private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + private static final String FULL_QUALIFIED_CLASS_NAME = "jvm_1/EmployeeV1"; - static String path1 = "D:\\workspace\\IDEA\\homework\\coding2017\\group17\\785396327\\out\\production\\785396327"; + static String path1 = "G:\\Git\\homework\\coding2017\\group17\\785396327\\3.12\\out\\production\\785396327"; static String path2 = "C:\temp"; static ClassFile clzFile = null; @@ -106,7 +107,7 @@ private String byteToHexString(byte[] codes ){ public void testVersion(){ Assert.assertEquals(0, clzFile.getMinorVersion()); - Assert.assertEquals(52, clzFile.getMajorVersion()); + Assert.assertEquals(51, clzFile.getMajorVersion()); } @@ -116,78 +117,78 @@ public void testConstantPool(){ ConstantPool pool = clzFile.getConstantPool(); -// Assert.assertEquals(53, pool.getSize()); + Assert.assertEquals(53, pool.getSize()); { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); - Assert.assertEquals(2, clzInfo.getUtf8Index()); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(7); + Assert.assertEquals(44, clzInfo.getUtf8Index()); -// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); -// Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(44); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(11); + Assert.assertEquals(48, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(48); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(12); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(13); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(14); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(15); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(16); + Assert.assertEquals("", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(17); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(18); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(1); + Assert.assertEquals(11, methodRef.getClassInfoIndex()); + Assert.assertEquals(36, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); } -// { -// ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); -// Assert.assertEquals(4, clzInfo.getUtf8Index()); -// -// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); -// Assert.assertEquals("java/lang/Object", utf8Info.getValue()); -// } -// { -// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); -// Assert.assertEquals("name", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(6); -// Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(7); -// Assert.assertEquals("age", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(8); -// Assert.assertEquals("I", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(9); -// Assert.assertEquals("", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(10); -// Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); -// -// utf8Info = (UTF8Info) pool.getConstantInfo(11); -// Assert.assertEquals("Code", utf8Info.getValue()); -// } -// -// { -// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); -// Assert.assertEquals(3, methodRef.getClassInfoIndex()); -// Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); -// } -// -// { -// NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); -// Assert.assertEquals(9, nameAndType.getIndex1()); -// Assert.assertEquals(14, nameAndType.getIndex2()); -// } -// //抽查几个吧 -// { -// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); -// Assert.assertEquals(1, methodRef.getClassInfoIndex()); -// Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); -// } -// -// { -// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); -// Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); -// } } @Test public void testClassIndex(){ -// ClassIndex clzIndex = clzFile.getClzIndex(); -// ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); -// ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); -// -// -// Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); -// Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } /** diff --git a/group17/785396327/4.5/util/Util.java b/group17/785396327/4.5/util/Util.java index f2e2b3d859..9b95c51ec4 100644 --- a/group17/785396327/4.5/util/Util.java +++ b/group17/785396327/4.5/util/Util.java @@ -1,7 +1,5 @@ package util; -import constant.ConstantPool; - /** * Created by IBM on 2017/4/10. */ From 92a7f4ad55d5ce68538d6abb2a9dddd37022b090 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 12 Apr 2017 20:09:36 +0800 Subject: [PATCH 019/151] jvm done --- group12/382266293/src/array/ArrayUtil.java | 256 +++++++++--------- .../382266293/src/array/ArrayUtilTest.java | 140 +++++----- .../coderising/download/DownloadThread.java | 23 +- .../com/coderising/download/DownloadUtil.java | 34 +-- .../coderising/download/FileDownloader.java | 98 +++---- .../download/FileDownloaderTest.java | 12 +- .../coderising/download/api/Connection.java | 30 +- .../download/impl/ConnectionImpl.java | 52 ++-- .../download/impl/ConnectionManagerImpl.java | 18 +- .../download/impl/DownloadUtil.java | 8 +- .../src/com/coderising/jvm/attr/CodeAttr.java | 76 +++--- .../coderising/jvm/attr/LineNumberTable.java | 50 +++- .../jvm/attr/LocalVariableItem.java | 30 +- .../jvm/attr/LocalVariableTable.java | 46 +++- .../coderising/jvm/attr/StackMapTable.java | 12 +- .../com/coderising/jvm/clz/AccessFlag.java | 18 +- .../src/com/coderising/jvm/clz/ClassFile.java | 78 +++--- .../com/coderising/jvm/clz/ClassIndex.java | 16 +- .../coderising/jvm/constant/ClassInfo.java | 21 +- .../coderising/jvm/constant/ConstantInfo.java | 8 +- .../coderising/jvm/constant/ConstantPool.java | 8 +- .../coderising/jvm/constant/FieldRefInfo.java | 48 ++-- .../jvm/constant/MethodRefInfo.java | 44 +-- .../jvm/constant/NameAndTypeInfo.java | 26 +- .../coderising/jvm/constant/StringInfo.java | 10 +- .../com/coderising/jvm/constant/UTF8Info.java | 19 +- .../src/com/coderising/jvm/field/Field.java | 42 ++- .../jvm/loader/ByteCodeIterator.java | 68 ++--- .../jvm/loader/ClassFileLoader.java | 72 ++--- .../jvm/loader/ClassFileParser.java | 71 +++-- .../src/com/coderising/jvm/method/Method.java | 81 +++--- .../jvm/test/ClassFileloaderTest.java | 143 +++++----- .../com/coderising/jvm/test/EmployeeV1.java | 20 +- .../src/com/coderising/jvm/util/Util.java | 10 +- .../coderising/litestruts/LoginAction.java | 24 +- .../src/litestruts/ActionXMLreader.java | 1 + .../src/litestruts/Configuration.java | 110 ++++---- group12/382266293/src/litestruts/Struts.java | 100 +++---- .../382266293/src/litestruts/StrutsTest.java | 20 +- group12/382266293/src/litestruts/View.java | 8 +- group12/382266293/src/test.java | 59 ++-- 41 files changed, 1034 insertions(+), 976 deletions(-) diff --git a/group12/382266293/src/array/ArrayUtil.java b/group12/382266293/src/array/ArrayUtil.java index ea847fd386..0abca4577f 100644 --- a/group12/382266293/src/array/ArrayUtil.java +++ b/group12/382266293/src/array/ArrayUtil.java @@ -8,106 +8,38 @@ public class ArrayUtil { - /** - * 给定一个整形数组a , 对该数组的值进行置换 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] 如果 a = - * [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * - * @param origin - * @return - */ - public void reverseArray(int[] origin) { - - int temp; - int index = origin.length - 1; - int numbersToReverse = origin.length / 2; - for (int i = 0; i < numbersToReverse; i++) { - temp = origin[i]; - origin[i] = origin[index - i]; - origin[index - i] = temp; + public static void initialArray(int[] arr, int j) { + for (int i = 0; i < arr.length; i++) { + arr[i] = j; } } - /** - * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: {1,3,4,5,6,6,5,4,7,6,7,5} - * - * @param oldArray - * @return - */ - - public int[] removeZero(int[] oldArray) { + public static boolean isPerfectNum(int num) { - BitSet check = new BitSet(oldArray.length); - boolean isZero; - for (int i = 0; i < oldArray.length; i++) { - isZero = (oldArray[i] == 0) ? true : false; - check.set(i, isZero); + int sum = 0; + for (int i = 1; i <= num / 2; i++) { + if (num % i == 0) + sum += i; } - int newSize = oldArray.length - check.cardinality(); - int[] newArr = new int[newSize]; - - int nextIndex = check.nextClearBit(0); - for (int i = 0; i < newSize; i++) { - newArr[i] = oldArray[nextIndex]; - nextIndex = check.nextClearBit(nextIndex + 1); - } + return (num == sum) ? true : false; - return newArr; } - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 例如 a1 = - * [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - * - * @param array1 - * @param array2 - * @return - */ + public static boolean isPrime(int num) { - public int[] merge(int[] array1, int[] array2) { + if (num <= 1) + return false; - int len1 = array1.length; - int len2 = array2.length; - int len3 = array1[len1 - 1] < array2[len2 - 1] ? array2[len2 - 1] + 1 : array1[len1 - 1] + 1; - int[] newArr = new int[len3]; - initialArray(newArr, -1); - for (int i = 0; i < len1; i++) { - newArr[array1[i]] = 0; - } - for (int i = 0; i < len2; i++) { - newArr[array2[i]] = 0; - } - int mergedLength = 0; - for (int i = 0; i < len3; i++) { - if (newArr[i] != -1) - newArr[mergedLength++] = i; - } - return Arrays.copyOf(newArr, mergedLength); - } + if (num == 2) + return true; - public static void initialArray(int[] arr, int j) { - for (int i = 0; i < arr.length; i++) { - arr[i] = j; + for (int i = 2; i <= Math.sqrt(num) + 1; i++) { + if (num % i == 0) + return false; } - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * - * @param oldArray - * @param size - * @return - */ - public int[] grow(int[] oldArray, int size) { - int[] newArr = new int[oldArray.length + size]; - for (int i = 0; i < oldArray.length; i++) { - newArr[i] = oldArray[i]; - } - return newArr; + return true; } /** @@ -131,6 +63,30 @@ public int[] fibonacci(int max) { return Arrays.copyOf(result, ++count); } + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public int[] getPerfectNumbers(int max) { + + int count = 0; + ArrayList myList = new ArrayList(); + for (int i = 1; i < max; i++) { + if (isPerfectNum(i)) { + count++; + myList.add(i); + } + } + int[] result = new int[count]; + Iterator iterator = myList.iterator(); + for (int i = 0; i < count; i++) { + result[i] = iterator.next(); + } + return result; + } + /** * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] * @@ -154,73 +110,117 @@ public int[] getPrimes(int max) { return result; } - public static boolean isPrime(int num) { - - if (num <= 1) - return false; - - if (num == 2) - return true; + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * + * @param oldArray + * @param size + * @return + */ + public int[] grow(int[] oldArray, int size) { - for (int i = 2; i <= Math.sqrt(num) + 1; i++) { - if (num % i == 0) - return false; + int[] newArr = new int[oldArray.length + size]; + for (int i = 0; i < oldArray.length; i++) { + newArr[i] = oldArray[i]; } + return newArr; + } - return true; + /** + * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + sb.append(array[i]); + if (i < array.length - 1) + sb.append(seperator); + } + return sb.toString(); } /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 例如 a1 = + * [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 * - * @param max + * @param array1 + * @param array2 * @return */ - public int[] getPerfectNumbers(int max) { - int count = 0; - ArrayList myList = new ArrayList(); - for (int i = 1; i < max; i++) { - if (isPerfectNum(i)) { - count++; - myList.add(i); - } + public int[] merge(int[] array1, int[] array2) { + + int len1 = array1.length; + int len2 = array2.length; + int len3 = array1[len1 - 1] < array2[len2 - 1] ? array2[len2 - 1] + 1 : array1[len1 - 1] + 1; + int[] newArr = new int[len3]; + initialArray(newArr, -1); + for (int i = 0; i < len1; i++) { + newArr[array1[i]] = 0; } - int[] result = new int[count]; - Iterator iterator = myList.iterator(); - for (int i = 0; i < count; i++) { - result[i] = iterator.next(); + for (int i = 0; i < len2; i++) { + newArr[array2[i]] = 0; } - return result; + int mergedLength = 0; + for (int i = 0; i < len3; i++) { + if (newArr[i] != -1) + newArr[mergedLength++] = i; + } + return Arrays.copyOf(newArr, mergedLength); } - public static boolean isPerfectNum(int num) { + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: {1,3,4,5,6,6,5,4,7,6,7,5} + * + * @param oldArray + * @return + */ - int sum = 0; - for (int i = 1; i <= num / 2; i++) { - if (num % i == 0) - sum += i; + public int[] removeZero(int[] oldArray) { + + BitSet check = new BitSet(oldArray.length); + boolean isZero; + for (int i = 0; i < oldArray.length; i++) { + isZero = (oldArray[i] == 0) ? true : false; + check.set(i, isZero); } - return (num == sum) ? true : false; + int newSize = oldArray.length - check.cardinality(); + int[] newArr = new int[newSize]; + + int nextIndex = check.nextClearBit(0); + for (int i = 0; i < newSize; i++) { + newArr[i] = oldArray[nextIndex]; + nextIndex = check.nextClearBit(nextIndex + 1); + } + return newArr; } /** - * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * 给定一个整形数组a , 对该数组的值进行置换 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] 如果 a = + * [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] * - * @param array - * @param s + * @param origin * @return */ - public String join(int[] array, String seperator) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - sb.append(array[i]); - if (i < array.length - 1) - sb.append(seperator); + public void reverseArray(int[] origin) { + + int temp; + int index = origin.length - 1; + int numbersToReverse = origin.length / 2; + for (int i = 0; i < numbersToReverse; i++) { + temp = origin[i]; + origin[i] = origin[index - i]; + origin[index - i] = temp; } - return sb.toString(); } } \ No newline at end of file diff --git a/group12/382266293/src/array/ArrayUtilTest.java b/group12/382266293/src/array/ArrayUtilTest.java index 031ef6c09b..d86ecde1fc 100644 --- a/group12/382266293/src/array/ArrayUtilTest.java +++ b/group12/382266293/src/array/ArrayUtilTest.java @@ -1,10 +1,14 @@ package array; -import static org.junit.Assert.*; -import static util.TestUtil.*; +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertArrayEquals; +import static util.TestUtil.getRandomIntArray; +import static util.TestUtil.getRandomNumber; + import java.util.Arrays; import java.util.Iterator; import java.util.TreeSet; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -25,43 +29,61 @@ public void tearDown() throws Exception { } @Test - public void testReverseArray() { + public void testFibonacci() { + int[] expected = new int[] { 1, 1, 2, 3, 5, 8, 13 }; + int[] acutal = new int[expected.length]; + actual = au.fibonacci(15); + assertArrayEquals(expected, actual); + } - int size = getRandomNumber(); - int[] expected = getRandomIntArray(size); - actual = Arrays.copyOf(expected, size); + @Test + public void testGetPerfectNumbers() { - au.reverseArray(actual); + int[] expected = new int[] { 6, 28, 496, 8128 }; + int[] acutal = new int[expected.length]; + actual = au.getPerfectNumbers(10000); + assertArrayEquals(expected, actual); + } - for (int i = 0; i < size; i++) { - assertEquals(expected[i], actual[size - 1 - i]); - } + @Test + public void testGetPrimes() { + int[] expected = new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }; + int[] acutal = new int[expected.length]; + actual = au.getPrimes(23); + assertArrayEquals(expected, actual); } @Test - public void testRemoveZero() { + public void testGrow() { + int[] expected = getRandomIntArray(getRandomNumber()); + int growSize = getRandomNumber(); + int[] actual = au.grow(expected, growSize); - int size = getRandomNumber(10000); - int[] expected = getRandomIntArray(size); + assertEquals(expected.length + growSize, actual.length); - int zeros = getRandomNumber(size - 1); - TreeSet t = new TreeSet(); - while (t.size() != zeros) { - t.add(getRandomNumber(size)); + for (int i = 0; i < actual.length; i++) { + if (i < expected.length) { + assertEquals(expected[i], actual[i]); + } else { + assertEquals(0, actual[i]); + } } - for (Integer i : t) { - expected[i] = 0; - } + } - int expectedSize = size - zeros; - actual = au.removeZero(expected); - assertEquals(expectedSize, actual.length); + @Test + public void testJoin() { - for (int i = 0, j = 0; i < size; i++) { - if (expected[i] != 0) - assertEquals(expected[i], actual[j++]); + int[] expected = getRandomIntArray(getRandomNumber()); + String seperator = "-"; + String joinedString = au.join(expected, seperator); + + String[] actual = joinedString.split(seperator); + + assertEquals(expected.length, actual.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], Integer.parseInt(actual[i])); } } @@ -92,61 +114,43 @@ public void testMerge() { } @Test - public void testGrow() { - int[] expected = getRandomIntArray(getRandomNumber()); - int growSize = getRandomNumber(); - int[] actual = au.grow(expected, growSize); + public void testRemoveZero() { - assertEquals(expected.length + growSize, actual.length); + int size = getRandomNumber(10000); + int[] expected = getRandomIntArray(size); - for (int i = 0; i < actual.length; i++) { - if (i < expected.length) { - assertEquals(expected[i], actual[i]); - } else { - assertEquals(0, actual[i]); - } + int zeros = getRandomNumber(size - 1); + TreeSet t = new TreeSet(); + while (t.size() != zeros) { + t.add(getRandomNumber(size)); } - } - - @Test - public void testFibonacci() { - int[] expected = new int[] { 1, 1, 2, 3, 5, 8, 13 }; - int[] acutal = new int[expected.length]; - actual = au.fibonacci(15); - assertArrayEquals(expected, actual); - } - - @Test - public void testGetPrimes() { + for (Integer i : t) { + expected[i] = 0; + } - int[] expected = new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }; - int[] acutal = new int[expected.length]; - actual = au.getPrimes(23); - assertArrayEquals(expected, actual); - } + int expectedSize = size - zeros; + actual = au.removeZero(expected); + assertEquals(expectedSize, actual.length); - @Test - public void testGetPerfectNumbers() { + for (int i = 0, j = 0; i < size; i++) { + if (expected[i] != 0) + assertEquals(expected[i], actual[j++]); + } - int[] expected = new int[] { 6, 28, 496, 8128 }; - int[] acutal = new int[expected.length]; - actual = au.getPerfectNumbers(10000); - assertArrayEquals(expected, actual); } @Test - public void testJoin() { + public void testReverseArray() { - int[] expected = getRandomIntArray(getRandomNumber()); - String seperator = "-"; - String joinedString = au.join(expected, seperator); + int size = getRandomNumber(); + int[] expected = getRandomIntArray(size); + actual = Arrays.copyOf(expected, size); - String[] actual = joinedString.split(seperator); + au.reverseArray(actual); - assertEquals(expected.length, actual.length); - for (int i = 0; i < expected.length; i++) { - assertEquals(expected[i], Integer.parseInt(actual[i])); + for (int i = 0; i < size; i++) { + assertEquals(expected[i], actual[size - 1 - i]); } } diff --git a/group12/382266293/src/com/coderising/download/DownloadThread.java b/group12/382266293/src/com/coderising/download/DownloadThread.java index 38f92f6677..11df6109e3 100644 --- a/group12/382266293/src/com/coderising/download/DownloadThread.java +++ b/group12/382266293/src/com/coderising/download/DownloadThread.java @@ -2,7 +2,6 @@ import java.io.File; import java.io.IOException; - import java.io.RandomAccessFile; import com.coderising.download.api.Connection; @@ -22,6 +21,15 @@ public DownloadThread(Connection conn, int startPos, int endPos) { this.endPos = endPos; } + public void close() { + this.conn.close(); + + } + + public void notifyFinished() { + fileDownloader.setThreadFinished(); + } + @Override public void run() { System.out.println(this.getName() + " is running"); @@ -49,21 +57,12 @@ public void run() { } } - public void setFileDownloader(FileDownloader fileDownloader) { - this.fileDownloader = fileDownloader; - } - - public void notifyFinished() { - fileDownloader.setThreadFinished(); - } - public void setDest(String dest) { this.dest = dest; } - public void close() { - this.conn.close(); - + public void setFileDownloader(FileDownloader fileDownloader) { + this.fileDownloader = fileDownloader; } } diff --git a/group12/382266293/src/com/coderising/download/DownloadUtil.java b/group12/382266293/src/com/coderising/download/DownloadUtil.java index c169214476..8e54afc2f9 100644 --- a/group12/382266293/src/com/coderising/download/DownloadUtil.java +++ b/group12/382266293/src/com/coderising/download/DownloadUtil.java @@ -9,8 +9,15 @@ public class DownloadUtil { private static final int MIN_CONNECTIONS = 3; private static final int MAX_CONNECTIONS = 10; - public static long getCurrentTime() { - return System.currentTimeMillis(); + public static int calculateConnects(int length) { + int conns = length / 1024 / 1024 / 10; + if (conns < MIN_CONNECTIONS) { + return MIN_CONNECTIONS; + } else if (conns > MAX_CONNECTIONS) { + return MAX_CONNECTIONS; + } else { + return conns; + } } public static void createTempFile(String tempName, int len) { @@ -44,15 +51,14 @@ public static void createTempFile(String tempName, int len) { } } - public static int calculateConnects(int length) { - int conns = length / 1024 / 1024 / 10; - if (conns < MIN_CONNECTIONS) { - return MIN_CONNECTIONS; - } else if (conns > MAX_CONNECTIONS) { - return MAX_CONNECTIONS; - } else { - return conns; - } + public static long getCurrentTime() { + return System.currentTimeMillis(); + } + + public static void printDownloadReport(int length, long start, long end) { + int time = (int) ((end - start) / 1000); + float speed = (float) length / 1024 / 1024 / time; + System.out.println("共耗时:" + time + "s,下载速度: " + (float) (Math.round(speed * 100)) / 100 + "Mb/s"); } public static boolean rename(String from, String to) { @@ -64,10 +70,4 @@ public static boolean rename(String from, String to) { return false; } - public static void printDownloadReport(int length, long start, long end) { - int time = (int) ((end - start) / 1000); - float speed = (float) length / 1024 / 1024 / time; - System.out.println("共耗时:" + time + "s,下载速度: " + (float) (Math.round(speed * 100)) / 100 + "Mb/s"); - } - } \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/download/FileDownloader.java b/group12/382266293/src/com/coderising/download/FileDownloader.java index 671ff7243c..311ebede84 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloader.java +++ b/group12/382266293/src/com/coderising/download/FileDownloader.java @@ -9,20 +9,45 @@ public class FileDownloader { private final static String EXT = "lyj"; private static DownloadThread[] threadPool; + private static String fileName; + private static String tempName; + private int finishedCount; public String downloadLocation; - String url; ConnectionManager cm; DownloadListener listener; - private static String fileName; - private static String tempName; public FileDownloader(String _url) { this.url = _url; this.finishedCount = 0; } + private boolean checkFinish(int links) { + + while (finishedCount != links) { + try { + Thread.sleep(5000); + System.out.println("Unfinshed threads number: " + (links - finishedCount)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return true; + } + + private void checkLength(int length, Connection conn) { + if (length <= 0) { + try { + throw new ConnectionException("file does not exist"); + } catch (ConnectionException e) { + e.printStackTrace(); + } finally { + conn.close(); + } + } + } + public void execute() { // 在这里实现你的代码, 注意: 需要用多线程实现下载 // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 @@ -75,44 +100,6 @@ public void execute() { } } - private void checkLength(int length, Connection conn) { - if (length <= 0) { - try { - throw new ConnectionException("file does not exist"); - } catch (ConnectionException e) { - e.printStackTrace(); - } finally { - conn.close(); - } - } - } - - private void setTempName(String name) { - String temp = name.substring(0, name.lastIndexOf(".") + 1) + EXT; - FileDownloader.tempName = downloadLocation + temp; - } - - private void setFileName(String name) { - FileDownloader.fileName = downloadLocation + name; - } - - private void setLocation(String downloadLocation) { - this.downloadLocation = downloadLocation; - } - - private boolean checkFinish(int links) { - - while (finishedCount != links) { - try { - Thread.sleep(5000); - System.out.println("Unfinshed threads number: " + (links - finishedCount)); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return true; - } - private void freeDownloadThread() { if (threadPool != null) { for (int i = 0; i < threadPool.length; i++) { @@ -134,6 +121,12 @@ public DownloadListener getListener() { return this.listener; } + private void setAndStartThread(DownloadThread downloadThread, String dest) { + downloadThread.setDest(dest); + downloadThread.setFileDownloader(this); + downloadThread.start(); + } + private void setAndStartThreadPool(Connection conn, DownloadThread[] threadPool, int length) throws ConnectionException { int connectionNumbers = threadPool.length; @@ -156,22 +149,29 @@ private void setAndStartThreadPool(Connection conn, DownloadThread[] threadPool, } } - private void setAndStartThread(DownloadThread downloadThread, String dest) { - downloadThread.setDest(dest); - downloadThread.setFileDownloader(this); - downloadThread.start(); - } - public void setConnectionManager(ConnectionManager ucm) { this.cm = ucm; } - public void setThreadFinished() { - finishedCount++; + private void setFileName(String name) { + FileDownloader.fileName = downloadLocation + name; } public void setListener(DownloadListener listener) { this.listener = listener; } + private void setLocation(String downloadLocation) { + this.downloadLocation = downloadLocation; + } + + private void setTempName(String name) { + String temp = name.substring(0, name.lastIndexOf(".") + 1) + EXT; + FileDownloader.tempName = downloadLocation + temp; + } + + public void setThreadFinished() { + finishedCount++; + } + } diff --git a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java index 88a5dba40e..b9c458d2a6 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java +++ b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java @@ -9,20 +9,20 @@ import com.coderising.download.impl.ConnectionManagerImpl; public class FileDownloaderTest { - boolean downloadFinished = false; + public static String qq = "http://sw.bos.baidu.com/sw-search-sp/software/89179b0b248b1/QQ_8.9.20026.0_setup.exe"; + + public static String picture = "http://image.beekka.com/blog/201304/bg2013042401.jpg"; + + public static String foxmail = "http://sw.bos.baidu.com/sw-search-sp/software/6c7bb8b6674d0/fm728chb379_7.2.8.379_setup.exe"; + boolean downloadFinished = false; @Before public void setUp() throws Exception { } - @After public void tearDown() throws Exception { } - public static String qq = "http://sw.bos.baidu.com/sw-search-sp/software/89179b0b248b1/QQ_8.9.20026.0_setup.exe"; - public static String picture = "http://image.beekka.com/blog/201304/bg2013042401.jpg"; - public static String foxmail = "http://sw.bos.baidu.com/sw-search-sp/software/6c7bb8b6674d0/fm728chb379_7.2.8.379_setup.exe"; - @Test public void testDownload() { diff --git a/group12/382266293/src/com/coderising/download/api/Connection.java b/group12/382266293/src/com/coderising/download/api/Connection.java index 11a0eab3d8..53293962a0 100644 --- a/group12/382266293/src/com/coderising/download/api/Connection.java +++ b/group12/382266293/src/com/coderising/download/api/Connection.java @@ -4,15 +4,10 @@ public interface Connection { /** - * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * - * @param startPos - * 开始位置, 从0开始 - * @param endPos - * 结束位置 - * @return + * 关闭连接 */ - public byte[] read(int startPos, int endPos) throws IOException; + + public void close(); /** * 得到数据内容的长度 @@ -21,15 +16,20 @@ public interface Connection { */ public int getContentLength(); - /** - * 关闭连接 - */ + public String getFileName(); - public void close(); + public boolean isFinished(); - public String getFileName(); + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * + * @param startPos + * 开始位置, 从0开始 + * @param endPos + * 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; public void setFinished(); - - public boolean isFinished(); } diff --git a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java index a4fa5c15ad..7c772bc665 100644 --- a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java +++ b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java @@ -12,8 +12,8 @@ public class ConnectionImpl implements Connection { - private ConnectionManager cm; private static int buffer_size = 1024; + private ConnectionManager cm; private HttpURLConnection httpConn; private URL url; private boolean finished = false; @@ -28,6 +28,31 @@ public ConnectionImpl(ConnectionManager cm, String _url) { } } + @Override + public void close() { + httpConn.disconnect(); + } + + @Override + public int getContentLength() { + int len = httpConn.getContentLength(); + + return len; + + } + + @Override + public String getFileName() { + String fileName = httpConn.getURL().getFile(); + fileName = fileName.substring(fileName.lastIndexOf('/') + 1); + return fileName; + } + + @Override + public boolean isFinished() { + return finished; + } + @Override public byte[] read(int startPos, int endPos) throws IOException { InputStream in = null; @@ -60,34 +85,9 @@ public byte[] read(int startPos, int endPos) throws IOException { return null; } - @Override - public int getContentLength() { - int len = httpConn.getContentLength(); - - return len; - - } - - @Override - public void close() { - httpConn.disconnect(); - } - - @Override - public String getFileName() { - String fileName = httpConn.getURL().getFile(); - fileName = fileName.substring(fileName.lastIndexOf('/') + 1); - return fileName; - } - @Override public void setFinished() { finished = true; } - @Override - public boolean isFinished() { - return finished; - } - } diff --git a/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java index 122073e37b..c4634733d5 100644 --- a/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java +++ b/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -16,6 +16,15 @@ public ConnectionManagerImpl() { this.connections = 0; } + private void checkConnectionSize() { + if (connections > MAX_CONNECTION_SIZE) + try { + throw new NoFreeSourceException("No free connections available."); + } catch (NoFreeSourceException e) { + e.printStackTrace(); + } + } + @Override public Connection open(String url) throws ConnectionException { this.url = url; @@ -33,13 +42,4 @@ public Connection open(String url) throws ConnectionException { return null; } - private void checkConnectionSize() { - if (connections > MAX_CONNECTION_SIZE) - try { - throw new NoFreeSourceException("No free connections available."); - } catch (NoFreeSourceException e) { - e.printStackTrace(); - } - } - } diff --git a/group12/382266293/src/com/coderising/download/impl/DownloadUtil.java b/group12/382266293/src/com/coderising/download/impl/DownloadUtil.java index 834a68d702..34521a5cd7 100644 --- a/group12/382266293/src/com/coderising/download/impl/DownloadUtil.java +++ b/group12/382266293/src/com/coderising/download/impl/DownloadUtil.java @@ -6,10 +6,6 @@ public class DownloadUtil { - public static long getCurrentTime() { - return System.currentTimeMillis(); - } - public static void createTempFile(String tempName, int len) { File file = new File(tempName); if (file.exists()) { @@ -41,4 +37,8 @@ public static void createTempFile(String tempName, int len) { } } + public static long getCurrentTime() { + return System.currentTimeMillis(); + } + } diff --git a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java index 68a628ec61..da9c2899a2 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java @@ -1,52 +1,13 @@ package com.coderising.jvm.attr; -import java.io.UnsupportedEncodingException; - import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; -import com.coderising.jvm.field.Field; import com.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(); - System.out.println("attrIndex " + attrNameIndex); - int attrLen = iter.nextU4ToInt(); int maxStack = iter.nextU2ToInt(); @@ -57,9 +18,9 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ System.out.println("codeLen " + codeLen); - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, "Code"); - String code = iter.nextUxToHexString(codeLen); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); System.out.println("Code is " + code); @@ -104,6 +65,39 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ return codeAttr; } + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String 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 String getCode() { + return code; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } private void setStackMapTable(StackMapTable t) { diff --git a/group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java b/group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java index 22941f83b1..f6a8c2e64b 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java +++ b/group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java @@ -6,35 +6,59 @@ import com.coderising.jvm.loader.ByteCodeIterator; public class LineNumberTable extends AttributeInfo { - List 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 int getStartPC() { + return startPC; + } public void setLineNum(int lineNum) { this.lineNum = lineNum; } + public void setStartPC(int startPC) { + this.startPC = startPC; + } } - public void addLineNumberItem(LineNumberItem item){ - this.items.add(item); + + public static LineNumberTable parse(ByteCodeIterator iter){ + + int attrNameIndex = iter.nextU2ToInt(); + + int attrLen = iter.nextU4ToInt(); + + int line_number_table_length = iter.nextU2ToInt(); + + LineNumberTable lnt = new LineNumberTable(attrNameIndex, attrLen); + + + for (int i = 0; i < line_number_table_length; i++) { + + LineNumberItem lni = new LineNumberItem(); + + int start_pc = iter.nextU2ToInt(); + lni.setStartPC(start_pc); + + int line_number = iter.nextU2ToInt(); + lni.setLineNum(line_number); + + lnt.addLineNumberItem(lni); + } + + + + return lnt; } + List items = new ArrayList(); public LineNumberTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - public static LineNumberTable parse(ByteCodeIterator iter){ - - return null; + public void addLineNumberItem(LineNumberItem item){ + this.items.add(item); } diff --git a/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java index 3eb2654e36..80f3af5cd5 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java +++ b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -6,34 +6,34 @@ public class LocalVariableItem { private int nameIndex; private int descIndex; private int index; - public int getStartPC() { - return startPC; + public int getDescIndex() { + return descIndex; } - public void setStartPC(int startPC) { - this.startPC = startPC; + public int getIndex() { + return index; } 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 int getStartPC() { + return startPC; } public void setDescIndex(int descIndex) { this.descIndex = descIndex; } - public int getIndex() { - return index; - } public void setIndex(int index) { this.index = index; } + public void setLength(int length) { + this.length = length; + } + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } } diff --git a/group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java index fa69dc9bdb..0028567ac1 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -4,25 +4,53 @@ import java.util.ArrayList; import java.util.List; -import com.coderising.jvm.constant.ConstantPool; - import com.coderising.jvm.loader.ByteCodeIterator; public class LocalVariableTable extends AttributeInfo{ - List items = new ArrayList(); + public static LocalVariableTable parse(ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2ToInt(); + + int attrLen = iter.nextU4ToInt(); + + int local_variable_table_length = iter.nextU2ToInt(); + + LocalVariableTable lvt = new LocalVariableTable(attrNameIndex, attrLen); + + + for (int i = 0; i < local_variable_table_length; i++) { + + LocalVariableItem lvi = new LocalVariableItem(); + + int start_pc = iter.nextU2ToInt(); + lvi.setStartPC(start_pc); + + int length = iter.nextU2ToInt(); + lvi.setLength(length); + + int name_index = iter.nextU2ToInt(); + lvi.setNameIndex(name_index); + + int desc_index = iter.nextU2ToInt(); + lvi.setDescIndex(desc_index); + + int index = iter.nextU2ToInt(); + lvi.setIndex(index); + + lvt.addLocalVariableItem(lvi); + } + + return lvt; + } + List items = new ArrayList(); + public LocalVariableTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - - public static LocalVariableTable parse(ByteCodeIterator iter){ - - return null; - } + private void addLocalVariableItem(LocalVariableItem item) { this.items.add(item); } - } diff --git a/group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java b/group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java index 44c5d90d46..0dd885a940 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java +++ b/group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java @@ -5,12 +5,6 @@ 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(); @@ -23,6 +17,12 @@ public static StackMapTable parse(ByteCodeIterator iter){ return t; } + private String originalCode; + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + private void setOriginalCode(String code) { this.originalCode = code; diff --git a/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java b/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java index 17dd61f8b6..20e86330df 100644 --- a/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java +++ b/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java @@ -3,6 +3,11 @@ import com.coderising.jvm.loader.ByteCodeIterator; public class AccessFlag { + public static AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + private int flagValue; public AccessFlag(int value) { @@ -13,20 +18,15 @@ public int getFlagValue() { return flagValue; } - public void setFlagValue(int flag) { - this.flagValue = flag; + public boolean isFinalClass() { + return (this.flagValue & 0x0010) != 0; } public boolean isPublicClass() { return (this.flagValue & 0x0001) != 0; } - public boolean isFinalClass() { - return (this.flagValue & 0x0010) != 0; - } - - public static AccessFlag parseAccessFlag(ByteCodeIterator iter) { - AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); - return accessFlag; + public void setFlagValue(int flag) { + this.flagValue = flag; } } \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java index 6e37d03643..58c21ac41b 100644 --- a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java @@ -19,45 +19,57 @@ public class ClassFile { private List fields = new ArrayList(); private List methods = new ArrayList(); - public ClassIndex getClzIndex() { - return clzIndex; + public void addField(Field field) { + + this.fields.add(field); + + } + + public void addMethod(Method method) { + + this.methods.add(method); + } public AccessFlag getAccessFlag() { return accessFlag; } - public void setAccessFlag(AccessFlag accessFlag) { - this.accessFlag = accessFlag; + private String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + public ClassIndex getClzIndex() { + return clzIndex; } public ConstantPool getConstantPool() { return pool; } - public int getMinorVersion() { - return minorVersion; - } + public List getFields() { - public void setMinorVersion(int minorVersion) { - this.minorVersion = minorVersion; + return fields; } public int getMajorVersion() { return majorVersion; } - public void setMajorVersion(int majorVersion) { - this.majorVersion = majorVersion; - } + public List getMethods() { - public void setConstPool(ConstantPool pool) { - this.pool = pool; + return methods; + } + public int getMinorVersion() { + return minorVersion; } - public void setClassIndex(ClassIndex clzIndex) { - this.clzIndex = clzIndex; + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); } public void print() { @@ -71,20 +83,17 @@ public void print() { } - private String getClassName() { - int thisClassIndex = this.clzIndex.getThisClassIndex(); - ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); - return thisClass.getClassName(); + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; } - private String getSuperClassName() { - ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); - return superClass.getClassName(); + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; } + + public void setConstPool(ConstantPool pool) { + this.pool = pool; - public List getFields() { - - return fields; } public void setFields(List fields) { @@ -92,16 +101,9 @@ public void setFields(List fields) { this.fields = fields; } - - public void addField(Field field) { - - this.fields.add(field); - - } - - public List getMethods() { - return methods; + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; } public void setMethods(List methods) { @@ -110,9 +112,7 @@ public void setMethods(List methods) { } - public void addMethod(Method method) { - - this.methods.add(method); - + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; } } diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java b/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java index 0212bc9fb3..213fb9163f 100644 --- a/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java @@ -4,19 +4,19 @@ public class ClassIndex { private int thisClassIndex; private int superClassIndex; - public int getThisClassIndex() { - return thisClassIndex; - } - - public void setThisClassIndex(int thisClassIndex) { - this.thisClassIndex = thisClassIndex; - } - public int getSuperClassIndex() { return superClassIndex; } + public int getThisClassIndex() { + return thisClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { this.superClassIndex = superClassIndex; } + + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } } \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java index 4b593e7347..083bfe73f0 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java @@ -8,21 +8,22 @@ public ClassInfo(ConstantPool pool) { super(pool); } - public int getUtf8Index() { - return utf8Index; - } - - public void setUtf8Index(int utf8Index) { - this.utf8Index = utf8Index; + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); + return utf8Info.getValue(); } + @Override public int getType() { return type; } - public String getClassName() { - int index = getUtf8Index(); - UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); - return utf8Info.getValue(); + public int getUtf8Index() { + return utf8Index; + } + + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java index 96845046b3..5366000a7b 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java @@ -19,14 +19,14 @@ public ConstantInfo(ConstantPool pool) { pool.addConstantInfo(this); } - public abstract int getType(); + public ConstantInfo getConstantInfo(int index) { + return this.constantPool.getConstantInfo(index); + } public ConstantPool getConstantPool() { return constantPool; } - public ConstantInfo getConstantInfo(int index) { - return this.constantPool.getConstantInfo(index); - } + public abstract int getType(); } diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java index 95c44dde8f..06b83239f4 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java @@ -22,11 +22,11 @@ public ConstantInfo getConstantInfo(int index) { return this.constantInfos.get(index); } - public String getUTF8String(int index) { - return ((UTF8Info) this.constantInfos.get(index)).getValue(); - } - public Object getSize() { return this.constantInfos.size() - 1; } + + public String getUTF8String(int index) { + return ((UTF8Info) this.constantInfos.get(index)).getValue(); + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java index e9f34e550c..6161ac4c06 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -9,33 +9,10 @@ public FieldRefInfo(ConstantPool pool) { super(pool); } - public int getType() { - return type; - } - public int getClassInfoIndex() { return classInfoIndex; } - public void setClassInfoIndex(int classInfoIndex) { - this.classInfoIndex = classInfoIndex; - } - - public int getNameAndTypeIndex() { - return nameAndTypeIndex; - } - - public void setNameAndTypeIndex(int nameAndTypeIndex) { - this.nameAndTypeIndex = nameAndTypeIndex; - } - - public String toString() { - - NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); - - return getClassName() + " : " + typeInfo.getName() + ":" + typeInfo.getTypeInfo() + "]"; - } - public String getClassName() { ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); @@ -55,4 +32,29 @@ public String getFieldType() { NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + @Override + public int getType() { + return type; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public String toString() { + + NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() + " : " + typeInfo.getName() + ":" + typeInfo.getTypeInfo() + "]"; + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java index d58de16f72..1330036966 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -11,31 +11,10 @@ public MethodRefInfo(ConstantPool pool) { super(pool); } - public int getType() { - return type; - } - public int getClassInfoIndex() { return classInfoIndex; } - public void setClassInfoIndex(int classInfoIndex) { - this.classInfoIndex = classInfoIndex; - } - - public int getNameAndTypeIndex() { - return nameAndTypeIndex; - } - - public void setNameAndTypeIndex(int nameAndTypeIndex) { - this.nameAndTypeIndex = nameAndTypeIndex; - } - - public String toString() { - - return getClassName() + " : " + this.getMethodName() + " : " + this.getParamAndReturnType(); - } - public String getClassName() { ConstantPool pool = this.getConstantPool(); ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(this.getClassInfoIndex()); @@ -48,10 +27,33 @@ public String getMethodName() { return typeInfo.getName(); } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public String getParamAndReturnType() { ConstantPool pool = this.getConstantPool(); NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public int getType() { + return type; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public String toString() { + + return getClassName() + " : " + this.getMethodName() + " : " + this.getParamAndReturnType(); + } + } diff --git a/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java index a792e2dc13..9ce0725fd3 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -14,34 +14,36 @@ public int getIndex1() { return index1; } - public void setIndex1(int index1) { - this.index1 = index1; - } - public int getIndex2() { return index2; } - public void setIndex2(int index2) { - this.index2 = index2; - } - - public int getType() { - return type; - } - public String getName() { ConstantPool pool = this.getConstantPool(); UTF8Info utf8Info1 = (UTF8Info) pool.getConstantInfo(index1); return utf8Info1.getValue(); } + @Override + public int getType() { + return type; + } + public String getTypeInfo() { ConstantPool pool = this.getConstantPool(); UTF8Info utf8Info2 = (UTF8Info) pool.getConstantInfo(index2); return utf8Info2.getValue(); } + public void setIndex1(int index1) { + this.index1 = index1; + } + + public void setIndex2(int index2) { + this.index2 = index2; + } + + @Override public String toString() { return "(" + getName() + "," + getTypeInfo() + ")"; } diff --git a/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java index 0ea1f6bdac..e900b990cf 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java @@ -8,18 +8,20 @@ public StringInfo(ConstantPool pool) { super(pool); } - public int getType() { - return type; - } - public int getIndex() { return index; } + @Override + public int getType() { + return type; + } + public void setIndex(int index) { this.index = index; } + @Override public String toString() { return this.getConstantPool().getUTF8String(index); } diff --git a/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java b/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java index a7e88969a4..b1179ad150 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java @@ -13,25 +13,26 @@ public int getLength() { return length; } - public void setLength(int length) { - this.length = length; - } - + @Override public int getType() { return type; } - @Override - public String toString() { - return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + ")]"; - } - public String getValue() { return value; } + public void setLength(int length) { + this.length = length; + } + public void setValue(String value) { this.value = value; } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + ")]"; + } + } diff --git a/group12/382266293/src/com/coderising/jvm/field/Field.java b/group12/382266293/src/com/coderising/jvm/field/Field.java index 2b0c549685..1349de930d 100644 --- a/group12/382266293/src/com/coderising/jvm/field/Field.java +++ b/group12/382266293/src/com/coderising/jvm/field/Field.java @@ -1,17 +1,34 @@ package com.coderising.jvm.field; -import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.constant.ConstantPool; -import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public class Field { + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int access_flags = iter.nextU2ToInt(); + int name_index = iter.nextU2ToInt(); + int descriptor_index = iter.nextU2ToInt(); + int attrbutes_count = iter.nextU2ToInt(); + + if (attrbutes_count != 0) { + throw new RuntimeException("field attrbutes_count is " + attrbutes_count); + } + + Field field = new Field(access_flags,name_index,descriptor_index,pool); + + return field; + } private int accessFlag; private int nameIndex; - private int descriptorIndex; + private int descriptorIndex; + private ConstantPool pool; + + + public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { @@ -21,28 +38,9 @@ public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool po this.pool = pool; } - - - @Override public String toString() { return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex) ; } - public static Field parse(ConstantPool pool,ByteCodeIterator iter){ - - int access_flags = iter.nextU2ToInt(); - int name_index = iter.nextU2ToInt(); - int descriptor_index = iter.nextU2ToInt(); - int attrbutes_count = iter.nextU2ToInt(); - - if (attrbutes_count != 0) { - throw new RuntimeException("field attrbutes_count is " + attrbutes_count); - } - - Field field = new Field(access_flags,name_index,descriptor_index,pool); - - return field; - } - } diff --git a/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java index 4b554a434a..5fa9ba7661 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -11,59 +11,59 @@ public ByteCodeIterator(byte[] codes) { this.codes = codes; } - public String nextU4ToHexString() { - byte[] u4 = new byte[] { codes[currPos++], codes[currPos++], codes[currPos++], codes[currPos++] }; - return Util.byteToHexString(u4); + public void back(int i) { + currPos = currPos - 2; + } + + public String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); } + public byte[] nextNbytesToHexString(int length) { + byte[] bytes = new byte[length]; + int len = currPos + length; + for(int j = 0; currPos < len; j++) { + bytes[j] = codes[currPos++]; + } + + return bytes; + } + public int nextU1ToInt() { byte[] u1 = new byte[] { codes[currPos++] }; return Util.byteToInt(u1); } - + + public int nextU2ToInt() { byte[] u2 = new byte[] { codes[currPos++], codes[currPos++] }; return Util.byteToInt(u2); } - public int nextU4ToInt() { + public String nextU4ToHexString() { byte[] u4 = new byte[] { codes[currPos++], codes[currPos++], codes[currPos++], codes[currPos++] }; - return Util.byteToInt(u4); + return Util.byteToHexString(u4); } - - public byte[] nextNbytesToHexString(int length) { - byte[] bytes = new byte[length]; - int len = currPos + length; - for(int j = 0; currPos < len; j++) { - bytes[j] = codes[currPos++]; - } - - return bytes; + public int nextU4ToInt() { + byte[] u4 = new byte[] { codes[currPos++], codes[currPos++], codes[currPos++], codes[currPos++] }; + return Util.byteToInt(u4); } - + public String nextUxToHexString(int length) { byte[] codes = nextNbytesToHexString(length); return byteToHexString(codes); } - - public String byteToHexString(byte[] codes) { - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < codes.length; i++) { - byte b = codes[i]; - int value = b & 0xFF; - String strHex = Integer.toHexString(value); - if (strHex.length() < 2) { - strHex = "0" + strHex; - } - buffer.append(strHex); - } - return buffer.toString(); - } - - public void back(int i) { - currPos = currPos - 2; - } } diff --git a/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java index 71a8b6fefa..135cf41dee 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -14,10 +14,40 @@ public class ClassFileLoader { private List clzPaths = new ArrayList(); - public byte[] readBinaryCode(String className) { + public void addClassPath(String path) { + clzPaths.add(path); + } - String clzFileName = "//" + className.replaceAll("\\.", "//") + ".class"; - return loadClassFile(clzFileName); + private File getClassFile(String clzFileName) { + + for (String path : clzPaths) { + File file = new File(path + "//" + clzFileName); + if (file.exists()) { + return file; + } + } + return null; + + } + + public String getClassPath() { + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < clzPaths.size(); i++) { + + sb.append(clzPaths.get(i)); + if (i < clzPaths.size() - 1) { + sb.append(";"); + } + + } + + return sb.toString(); + } + + public String getClassPath_V1() { + + return null; } public ClassFile loadClass(String className) throws UnsupportedEncodingException { @@ -65,40 +95,10 @@ private byte[] loadClassFile(String clzFileName) { } - private File getClassFile(String clzFileName) { - - for (String path : clzPaths) { - File file = new File(path + "//" + clzFileName); - if (file.exists()) { - return file; - } - } - return null; - - } - - public void addClassPath(String path) { - clzPaths.add(path); - } - - public String getClassPath_V1() { - - return null; - } - - public String getClassPath() { - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < clzPaths.size(); i++) { - - sb.append(clzPaths.get(i)); - if (i < clzPaths.size() - 1) { - sb.append(";"); - } - - } + public byte[] readBinaryCode(String className) { - return sb.toString(); + String clzFileName = "//" + className.replaceAll("\\.", "//") + ".class"; + return loadClassFile(clzFileName); } } diff --git a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java index e1c997d3d0..b29cfe1d45 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java @@ -1,10 +1,6 @@ package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; @@ -19,7 +15,6 @@ import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; -import com.coderising.jvm.util.Util; public class ClassFileParser { @@ -62,39 +57,6 @@ public ClassFile parse(byte[] codes) { return clzFile; } - private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { - - int methodNum = iter.nextU2ToInt(); - - ConstantPool pool = clzFile.getConstantPool(); - for (int i = 0; i < methodNum; i++) { - Method method = Method.parse(clzFile,iter); - clzFile.addMethod(method); - } - - } - - private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { - - int fieldNum = iter.nextU2ToInt(); - - ConstantPool pool = clzFile.getConstantPool(); - for (int i = 0; i < fieldNum; i++) { - Field field = Field.parse(pool,iter); - clzFile.addField(field); - } - - } - - private void parseInterfaces(ByteCodeIterator iter) { - int interfaceNum = iter.nextU2ToInt(); - - if (0 != interfaceNum) { - throw new RuntimeException("interface parser not finsihed yet, pls check!"); - } - - } - private AccessFlag parseAccessFlag(ByteCodeIterator iter) { return AccessFlag.parseAccessFlag(iter); @@ -188,4 +150,37 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { return pool; } + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + + int fieldNum = iter.nextU2ToInt(); + + ConstantPool pool = clzFile.getConstantPool(); + for (int i = 0; i < fieldNum; i++) { + Field field = Field.parse(pool,iter); + clzFile.addField(field); + } + + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceNum = iter.nextU2ToInt(); + + if (0 != interfaceNum) { + throw new RuntimeException("interface parser not finsihed yet, pls check!"); + } + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + + int methodNum = iter.nextU2ToInt(); + + ConstantPool pool = clzFile.getConstantPool(); + for (int i = 0; i < methodNum; i++) { + Method method = Method.parse(clzFile,iter); + clzFile.addMethod(method); + } + + } + } diff --git a/group12/382266293/src/com/coderising/jvm/method/Method.java b/group12/382266293/src/com/coderising/jvm/method/Method.java index 3c3e026a40..b77ff6271b 100644 --- a/group12/382266293/src/com/coderising/jvm/method/Method.java +++ b/group12/382266293/src/com/coderising/jvm/method/Method.java @@ -1,61 +1,20 @@ package com.coderising.jvm.method; -import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; -import com.coderising.jvm.constant.ConstantPool; -import com.coderising.jvm.constant.UTF8Info; -import com.coderising.jvm.field.Field; +import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.loader.ByteCodeIterator; -import com.sun.org.apache.bcel.internal.classfile.Code; 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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ int access_flags = iter.nextU2ToInt(); int name_index = iter.nextU2ToInt(); int descriptor_index = iter.nextU2ToInt(); int attrbutes_count = iter.nextU2ToInt(); - System.out.println("count1 = " + attrbutes_count); Method method = new Method(clzFile, access_flags,name_index,descriptor_index); @@ -65,8 +24,10 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ iter.back(2); if (AttributeInfo.CODE.equalsIgnoreCase("Code")) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); method.setCodeAttr(codeAttr); + } else { throw new RuntimeException(att_name + "has not been implemented"); } @@ -78,4 +39,40 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return method; } + private int accessFlag; + private int nameIndex; + + private int descriptorIndex; + + private CodeAttr codeAttr; + + + private ClassFile clzFile; + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + public ClassFile getClzFile() { + return clzFile; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public int getNameIndex() { + return nameIndex; + } + + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } } diff --git a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java index d4f255a763..15050a0d76 100644 --- a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,7 +1,6 @@ package com.coderising.jvm.test; import java.io.UnsupportedEncodingException; -import java.util.Arrays; import java.util.List; import org.junit.After; @@ -11,7 +10,11 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; -import com.coderising.jvm.constant.*; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; import com.coderising.jvm.method.Method; @@ -20,9 +23,8 @@ public class ClassFileloaderTest { static String path1 = "C:\\Users\\steve\\workspace\\coding2017n\\group12\\382266293\\bin"; static String path2 = "C:\temp"; - String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static ClassFile clzFile = null; + static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); @@ -36,6 +38,30 @@ public class ClassFileloaderTest { } clzFile.print(); } + String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + 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); + } + + private String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } @Before public void setUp() throws Exception { @@ -45,19 +71,6 @@ public void setUp() throws Exception { public void tearDown() throws Exception { } - @Test - public void testClassPath() { - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - loader.addClassPath(path2); - - String clzPath = loader.getClassPath(); - - Assert.assertEquals(path1 + ";" + path2, clzPath); - - } - @Test public void testClassFileLength() { @@ -74,37 +87,26 @@ public void testClassFileLength() { } @Test - public void testMagicNumber() { - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - byte[] codes = new byte[] { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; - - String acctualValue = this.byteToHexString(codes); + public void testClassIndex() { - Assert.assertEquals("cafebabe", acctualValue); - } + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); - private String byteToHexString(byte[] codes) { - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < codes.length; i++) { - byte b = codes[i]; - int value = b & 0xFF; - String strHex = Integer.toHexString(value); - if (strHex.length() < 2) { - strHex = "0" + strHex; - } - buffer.append(strHex); - } - return buffer.toString(); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } @Test - public void testVersion() { + public void testClassPath() { - Assert.assertEquals(0, clzFile.getMinorVersion()); - Assert.assertEquals(52, clzFile.getMajorVersion()); + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); } @@ -177,31 +179,19 @@ public void testConstantPool() { } @Test - public void testClassIndex() { + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[] { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; - ClassIndex clzIndex = clzFile.getClzIndex(); - ClassInfo thisClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); - ClassInfo superClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + String acctualValue = this.byteToHexString(codes); - Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); - Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + Assert.assertEquals("cafebabe", acctualValue); } - @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(){ @@ -247,15 +237,28 @@ public void testMethods(){ "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); + @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 testVersion() { + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java b/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java index d36b122f60..24c0cae543 100644 --- a/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java +++ b/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java @@ -2,7 +2,13 @@ public class EmployeeV1 { + public static void main(String[] args) { + EmployeeV1 p = new EmployeeV1("Andy", 29); + p.sayHello(); + + } private String name; + private int age; public EmployeeV1(String name, int age) { @@ -10,21 +16,15 @@ public EmployeeV1(String name, int age) { this.age = age; } - public void setName(String name) { - this.name = name; + public void sayHello() { + System.out.println("Hello , this is class Employee "); } public void setAge(int age) { this.age = age; } - public void sayHello() { - System.out.println("Hello , this is class Employee "); - } - - public static void main(String[] args) { - EmployeeV1 p = new EmployeeV1("Andy", 29); - p.sayHello(); - + public void setName(String name) { + this.name = name; } } \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/jvm/util/Util.java b/group12/382266293/src/com/coderising/jvm/util/Util.java index 1f9e087bb9..c2042deaac 100644 --- a/group12/382266293/src/com/coderising/jvm/util/Util.java +++ b/group12/382266293/src/com/coderising/jvm/util/Util.java @@ -1,11 +1,6 @@ package com.coderising.jvm.util; public class Util { - public static int byteToInt(byte[] codes) { - String s1 = byteToHexString(codes); - return Integer.valueOf(s1, 16).intValue(); - } - public static String byteToHexString(byte[] codes) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < codes.length; i++) { @@ -19,4 +14,9 @@ public static String byteToHexString(byte[] codes) { } return buffer.toString(); } + + public static int byteToInt(byte[] codes) { + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } } diff --git a/group12/382266293/src/com/coderising/litestruts/LoginAction.java b/group12/382266293/src/com/coderising/litestruts/LoginAction.java index 95fd144d4d..7d1cf06a48 100644 --- a/group12/382266293/src/com/coderising/litestruts/LoginAction.java +++ b/group12/382266293/src/com/coderising/litestruts/LoginAction.java @@ -11,14 +11,6 @@ public class LoginAction { private String password; private String message; - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - public String execute() { if ("test".equals(name) && "1234".equals(password)) { this.message = "login successful"; @@ -28,6 +20,18 @@ public String execute() { return "fail"; } + public String getMessage() { + return this.message; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + public void setName(String name) { this.name = name; } @@ -35,8 +39,4 @@ public void setName(String name) { public void setPassword(String password) { this.password = password; } - - public String getMessage() { - return this.message; - } } \ No newline at end of file diff --git a/group12/382266293/src/litestruts/ActionXMLreader.java b/group12/382266293/src/litestruts/ActionXMLreader.java index 92e700edc4..53d815c174 100644 --- a/group12/382266293/src/litestruts/ActionXMLreader.java +++ b/group12/382266293/src/litestruts/ActionXMLreader.java @@ -1,6 +1,7 @@ package litestruts; import java.util.List; + import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; diff --git a/group12/382266293/src/litestruts/Configuration.java b/group12/382266293/src/litestruts/Configuration.java index 731a4218b0..44b85c9b45 100644 --- a/group12/382266293/src/litestruts/Configuration.java +++ b/group12/382266293/src/litestruts/Configuration.java @@ -1,25 +1,47 @@ package litestruts; +import static util.Print.println; + import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; + import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; -import static util.Print.*; public class Configuration { - Map actions = new HashMap<>(); + private static class ActionCfg { - private static Configuration cfg = new Configuration(); + String name; + String clz; + Map viewResult = new HashMap<>(); - private Configuration() { + public ActionCfg(String name, String clz) { + this.name = name; + this.clz = clz; + } + + public void addViewResult(String result, String jsp) { + viewResult.put(result, jsp); + + } + + public String getClassName() { + return clz; + } + + public Map getViewResult() { + return viewResult; + } } + private static Configuration cfg = new Configuration(); + public static Configuration getNewInstance() { if (cfg == null) { @@ -28,6 +50,36 @@ public static Configuration getNewInstance() { return cfg; } + public static void main(String[] args) { + Configuration cfg = new Configuration(); + cfg.parse("struts.xml"); + String clz = cfg.getClassName("login"); + println(clz); + + } + + Map actions = new HashMap<>(); + + private Configuration() { + + } + + public String getClassName(String action) { + ActionCfg cfg = this.actions.get(action); + if (cfg == null) { + return null; + } + return cfg.getClassName(); + } + + public String getResultView(String action, String resultName) { + ActionCfg cfg = this.actions.get(action); + if (cfg == null) { + return null; + } + return cfg.getViewResult().get(resultName); + } + public void parse(String fileName) { String src = this.getClass().getPackage().getName(); @@ -73,54 +125,4 @@ public void parseXML(InputStream is) { } } - public String getClassName(String action) { - ActionCfg cfg = this.actions.get(action); - if (cfg == null) { - return null; - } - return cfg.getClassName(); - } - - public String getResultView(String action, String resultName) { - ActionCfg cfg = this.actions.get(action); - if (cfg == null) { - return null; - } - return cfg.getViewResult().get(resultName); - } - - public static void main(String[] args) { - Configuration cfg = new Configuration(); - cfg.parse("struts.xml"); - String clz = cfg.getClassName("login"); - println(clz); - - } - - private static class ActionCfg { - - String name; - String clz; - Map viewResult = new HashMap<>(); - - public Map getViewResult() { - return viewResult; - } - - public ActionCfg(String name, String clz) { - this.name = name; - this.clz = clz; - } - - public void addViewResult(String result, String jsp) { - viewResult.put(result, jsp); - - } - - public String getClassName() { - return clz; - } - - } - } diff --git a/group12/382266293/src/litestruts/Struts.java b/group12/382266293/src/litestruts/Struts.java index b84e2e6264..2371cdbcd8 100644 --- a/group12/382266293/src/litestruts/Struts.java +++ b/group12/382266293/src/litestruts/Struts.java @@ -1,6 +1,5 @@ package litestruts; -import util.ActionXMLreader; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -9,33 +8,26 @@ import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; + import org.dom4j.Node; +import util.ActionXMLreader; + public class Struts { private static Object actionObj = null; private static String address = "src/litestruts/struts.xml"; private static ActionXMLreader reader = new ActionXMLreader(); - @SuppressWarnings("unchecked") - public static View runAction(String actionName, Map parameters) { - - Node root = reader.getRootNode(address); - String clazz = reader.parseClass(root, actionName); - actionObj = getObj(clazz); - BeanInfo bi = getBeanInfo(actionObj); - PropertyDescriptor[] pd = bi.getPropertyDescriptors(); - - setParameters(actionObj, pd, parameters); - String executeResult = getResult(actionObj, bi, "execute"); - String jsp = reader.parseResult(root, actionName, executeResult); - Map readParamters = getReadParameters(actionObj, pd); - - View view = new View(); - view.setJsp(jsp); - view.setParameters(readParamters); + private static BeanInfo getBeanInfo(Object obj) { - return view; + BeanInfo bi = null; + try { + bi = Introspector.getBeanInfo(obj.getClass(), Object.class); + } catch (IntrospectionException e) { + e.printStackTrace(); + } + return bi; } private static Object getObj(String clazz) { @@ -53,28 +45,22 @@ private static Object getObj(String clazz) { return null; } - private static BeanInfo getBeanInfo(Object obj) { - - BeanInfo bi = null; - try { - bi = Introspector.getBeanInfo(obj.getClass(), Object.class); - } catch (IntrospectionException e) { - e.printStackTrace(); - } - return bi; - } + @SuppressWarnings("rawtypes") + public static Map getReadParameters(Object obj, PropertyDescriptor[] pd) { - private static void setParameters(Object obj, PropertyDescriptor[] pd, Map parameters) { + Map viewParams = new HashMap(); for (int i = 0; i < pd.length; i++) { - String name = pd[i].getName(); - if (parameters.containsKey(name)) - try { - pd[i].getWriteMethod().invoke(obj, parameters.get(name)); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - e.printStackTrace(); - } + String readMethod = pd[i].getReadMethod().getName().substring(3); + String value = null; + try { + value = (String) pd[i].getReadMethod().invoke(obj); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + viewParams.put(readMethod.toLowerCase(), value); } + return viewParams; } private static String getResult(Object obj, BeanInfo bi, String execute) { @@ -91,22 +77,38 @@ private static String getResult(Object obj, BeanInfo bi, String execute) { return null; } - @SuppressWarnings("rawtypes") - public static Map getReadParameters(Object obj, PropertyDescriptor[] pd) { + @SuppressWarnings("unchecked") + public static View runAction(String actionName, Map parameters) { - Map viewParams = new HashMap(); + Node root = reader.getRootNode(address); + String clazz = reader.parseClass(root, actionName); + actionObj = getObj(clazz); + BeanInfo bi = getBeanInfo(actionObj); + PropertyDescriptor[] pd = bi.getPropertyDescriptors(); + + setParameters(actionObj, pd, parameters); + String executeResult = getResult(actionObj, bi, "execute"); + String jsp = reader.parseResult(root, actionName, executeResult); + Map readParamters = getReadParameters(actionObj, pd); + + View view = new View(); + view.setJsp(jsp); + view.setParameters(readParamters); + + return view; + } + + private static void setParameters(Object obj, PropertyDescriptor[] pd, Map parameters) { for (int i = 0; i < pd.length; i++) { - String readMethod = pd[i].getReadMethod().getName().substring(3); - String value = null; - try { - value = (String) pd[i].getReadMethod().invoke(obj); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - e.printStackTrace(); - } - viewParams.put(readMethod.toLowerCase(), value); + String name = pd[i].getName(); + if (parameters.containsKey(name)) + try { + pd[i].getWriteMethod().invoke(obj, parameters.get(name)); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } } - return viewParams; } } \ No newline at end of file diff --git a/group12/382266293/src/litestruts/StrutsTest.java b/group12/382266293/src/litestruts/StrutsTest.java index b450d7a935..8d70a91cb3 100644 --- a/group12/382266293/src/litestruts/StrutsTest.java +++ b/group12/382266293/src/litestruts/StrutsTest.java @@ -9,30 +9,30 @@ public class StrutsTest { @Test - public void testLoginActionSuccess() { - + public void testLoginActionFailed() { String actionName = "login"; - Map params = new HashMap(); params.put("name", "test"); - params.put("password", "1234"); + params.put("password", "123456"); // 密码和预设的不一致 View view = Struts.runAction(actionName, params); - Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); - Assert.assertEquals("login successful", view.getParameters().get("message")); + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); } @Test - public void testLoginActionFailed() { + public void testLoginActionSuccess() { + String actionName = "login"; + Map params = new HashMap(); params.put("name", "test"); - params.put("password", "123456"); // 密码和预设的不一致 + params.put("password", "1234"); View view = Struts.runAction(actionName, params); - Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); - Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); } } diff --git a/group12/382266293/src/litestruts/View.java b/group12/382266293/src/litestruts/View.java index 0c917dcb35..41152f3214 100644 --- a/group12/382266293/src/litestruts/View.java +++ b/group12/382266293/src/litestruts/View.java @@ -10,15 +10,15 @@ public String getJsp() { return jsp; } + public Map getParameters() { + return parameters; + } + public View setJsp(String jsp) { this.jsp = jsp; return this; } - public Map getParameters() { - return parameters; - } - public View setParameters(Map parameters) { this.parameters = parameters; return this; diff --git a/group12/382266293/src/test.java b/group12/382266293/src/test.java index b3a32d2556..3910b896af 100644 --- a/group12/382266293/src/test.java +++ b/group12/382266293/src/test.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.net.URL; import java.util.LinkedList; + import sun.net.www.protocol.http.HttpURLConnection; public class test { @@ -16,30 +17,6 @@ public class test { public static String tempName = ""; public static String fileName = ""; - LinkedList a; - - private static void createTempFile1(String from) { - long length = 0; - URL url = null; - HttpURLConnection conn = null; - try { - url = new URL(from); - conn = (HttpURLConnection) url.openConnection(); - String file = conn.getURL().getFile(); - fileName = file.substring(file.lastIndexOf('/') + 1); - tempName = fileName.substring(0, fileName.lastIndexOf('.') + 1) + "lyj"; - length = conn.getContentLength(); - conn.disconnect(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - conn.disconnect(); - } - tempName = downloadLocation + tempName; - fileName = downloadLocation + fileName; - bufferFile(tempName, length); - } - public static void bufferFile(String name, long len) { FileOutputStream temp = null; @@ -66,6 +43,28 @@ public static void bufferFile(String name, long len) { } } + private static void createTempFile1(String from) { + long length = 0; + URL url = null; + HttpURLConnection conn = null; + try { + url = new URL(from); + conn = (HttpURLConnection) url.openConnection(); + String file = conn.getURL().getFile(); + fileName = file.substring(file.lastIndexOf('/') + 1); + tempName = fileName.substring(0, fileName.lastIndexOf('.') + 1) + "lyj"; + length = conn.getContentLength(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + conn.disconnect(); + } + tempName = downloadLocation + tempName; + fileName = downloadLocation + fileName; + bufferFile(tempName, length); + } + public static void download(String src) { createTempFile1(src); @@ -95,6 +94,12 @@ public static void download(String src) { } + public static void main(String[] args) throws IOException { + + download(url2); + + } + public static boolean rename(String temp) { File file = new File(temp); File f1 = new File(fileName); @@ -107,10 +112,6 @@ public static boolean rename(String temp) { return false; } - public static void main(String[] args) throws IOException { - - download(url2); - - } + LinkedList a; } From f19f62afdb72ea810e19f2ba817c6c034fd11216 Mon Sep 17 00:00:00 2001 From: gongxun Date: Wed, 12 Apr 2017 23:35:16 +0800 Subject: [PATCH 020/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E8=A1=A8=E5=92=8C=E5=B1=9E=E6=80=A7=E8=A1=A8=E7=9A=84=E6=A1=86?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.5/clz/ClassFile.java | 33 ++--- group17/785396327/4.5/stack/StackUtil.java | 2 +- .../4.5/test/ClassFileloaderTest.java | 118 +++++++++--------- group17/785396327/4.9/attr/AttributeInfo.java | 20 +++ group17/785396327/4.9/attr/CodeAttr.java | 55 ++++++++ .../785396327/4.9/attr/LineNumberTable.java | 44 +++++++ .../785396327/4.9/attr/LocalVariableItem.java | 42 +++++++ .../4.9/attr/LocalVariableTable.java | 27 ++++ group17/785396327/4.9/attr/StackMapTable.java | 32 +++++ group17/785396327/4.9/field/Field.java | 33 +++++ group17/785396327/4.9/method/Method.java | 52 ++++++++ 11 files changed, 385 insertions(+), 73 deletions(-) create mode 100644 group17/785396327/4.9/attr/AttributeInfo.java create mode 100644 group17/785396327/4.9/attr/CodeAttr.java create mode 100644 group17/785396327/4.9/attr/LineNumberTable.java create mode 100644 group17/785396327/4.9/attr/LocalVariableItem.java create mode 100644 group17/785396327/4.9/attr/LocalVariableTable.java create mode 100644 group17/785396327/4.9/attr/StackMapTable.java create mode 100644 group17/785396327/4.9/field/Field.java create mode 100644 group17/785396327/4.9/method/Method.java diff --git a/group17/785396327/4.5/clz/ClassFile.java b/group17/785396327/4.5/clz/ClassFile.java index d4a8b8ed0c..e65cfbda81 100644 --- a/group17/785396327/4.5/clz/ClassFile.java +++ b/group17/785396327/4.5/clz/ClassFile.java @@ -2,6 +2,11 @@ import constant.ClassInfo; import constant.ConstantPool; +import field.Field; +import method.Method; + +import java.util.ArrayList; +import java.util.List; /** * Created by IBM on 2017/4/10. @@ -13,8 +18,8 @@ public class ClassFile { private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; -// private List fields = new ArrayList(); -// private List methods = new ArrayList(); + private List fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -51,18 +56,18 @@ public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } -// 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 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 print(){ diff --git a/group17/785396327/4.5/stack/StackUtil.java b/group17/785396327/4.5/stack/StackUtil.java index aa821a50ae..afaa5fce1b 100644 --- a/group17/785396327/4.5/stack/StackUtil.java +++ b/group17/785396327/4.5/stack/StackUtil.java @@ -110,6 +110,6 @@ public static boolean isValidPairs(String s) { return false; } } - return true; + return stack.size() == 0;//最后判断stack中没有元素了,可能有单个括号 } } diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 9f76c4ccbc..f1361b07a0 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -3,13 +3,15 @@ import clz.ClassFile; import clz.ClassIndex; import constant.*; +import field.Field; import jvm_1.ClassFileLoader; +import method.Method; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.lang.reflect.Method; +import java.util.List; /** * Created by IBM on 2017/4/10. @@ -197,70 +199,70 @@ public void testClassIndex(){ @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()); -// } + 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"); -// } + 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); + 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); } } diff --git a/group17/785396327/4.9/attr/AttributeInfo.java b/group17/785396327/4.9/attr/AttributeInfo.java new file mode 100644 index 0000000000..0a8a0c60c9 --- /dev/null +++ b/group17/785396327/4.9/attr/AttributeInfo.java @@ -0,0 +1,20 @@ +package attr; + +/** + * Created by IBM on 2017/4/12. + */ +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/group17/785396327/4.9/attr/CodeAttr.java b/group17/785396327/4.9/attr/CodeAttr.java new file mode 100644 index 0000000000..b069203d4f --- /dev/null +++ b/group17/785396327/4.9/attr/CodeAttr.java @@ -0,0 +1,55 @@ +package attr; + +import clz.ClassFile; +import iterator.ByteCodeIterator; + +/** + * Created by IBM on 2017/4/12. + */ +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) { + + + return null; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group17/785396327/4.9/attr/LineNumberTable.java b/group17/785396327/4.9/attr/LineNumberTable.java new file mode 100644 index 0000000000..f875aa2427 --- /dev/null +++ b/group17/785396327/4.9/attr/LineNumberTable.java @@ -0,0 +1,44 @@ +package attr; + +import iterator.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by IBM on 2017/4/12. + */ +public class LineNumberTable extends AttributeInfo { + List 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){ + + return null; + } + + +} diff --git a/group17/785396327/4.9/attr/LocalVariableItem.java b/group17/785396327/4.9/attr/LocalVariableItem.java new file mode 100644 index 0000000000..d0213e92f5 --- /dev/null +++ b/group17/785396327/4.9/attr/LocalVariableItem.java @@ -0,0 +1,42 @@ +package attr; + +/** + * Created by IBM on 2017/4/12. + */ +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/group17/785396327/4.9/attr/LocalVariableTable.java b/group17/785396327/4.9/attr/LocalVariableTable.java new file mode 100644 index 0000000000..060ed31e85 --- /dev/null +++ b/group17/785396327/4.9/attr/LocalVariableTable.java @@ -0,0 +1,27 @@ +package attr; + +import iterator.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by IBM on 2017/4/12. + */ +public class LocalVariableTable extends AttributeInfo { + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter) { + + return null; + } + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + +} diff --git a/group17/785396327/4.9/attr/StackMapTable.java b/group17/785396327/4.9/attr/StackMapTable.java new file mode 100644 index 0000000000..8de15ac552 --- /dev/null +++ b/group17/785396327/4.9/attr/StackMapTable.java @@ -0,0 +1,32 @@ +package attr; + +import iterator.ByteCodeIterator; + +/** + * Created by IBM on 2017/4/12. + */ +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; + return null; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group17/785396327/4.9/field/Field.java b/group17/785396327/4.9/field/Field.java new file mode 100644 index 0000000000..896398d113 --- /dev/null +++ b/group17/785396327/4.9/field/Field.java @@ -0,0 +1,33 @@ +package field; + +import constant.ConstantPool; +import iterator.ByteCodeIterator; + +/** + * Created by IBM on 2017/4/12. + */ +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 static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + return null; + } +} diff --git a/group17/785396327/4.9/method/Method.java b/group17/785396327/4.9/method/Method.java new file mode 100644 index 0000000000..f3b51fd15d --- /dev/null +++ b/group17/785396327/4.9/method/Method.java @@ -0,0 +1,52 @@ +package method; + +import attr.CodeAttr; +import clz.ClassFile; +import iterator.ByteCodeIterator; + +/** + * Created by IBM on 2017/4/12. + */ +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 static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + return null; + + } +} From 3337260d88d42451efc3d44e68eec4ca3281be59 Mon Sep 17 00:00:00 2001 From: gongxun Date: Thu, 13 Apr 2017 18:57:00 +0800 Subject: [PATCH 021/151] =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4.5/iterator/ByteCodeIterator.java | 7 ++++- .../785396327/4.5/parse/ClassFilePaser.java | 28 ++++++++++++++++- .../4.5/test/ClassFileloaderTest.java | 4 +-- group17/785396327/4.9/attr/CodeAttr.java | 31 +++++++++++++++++-- .../785396327/4.9/attr/LineNumberTable.java | 19 +++++++++--- .../4.9/attr/LocalVariableTable.java | 21 +++++++++++-- group17/785396327/4.9/field/Field.java | 20 ++++++++---- group17/785396327/4.9/method/Method.java | 12 ++++++- 8 files changed, 122 insertions(+), 20 deletions(-) diff --git a/group17/785396327/4.5/iterator/ByteCodeIterator.java b/group17/785396327/4.5/iterator/ByteCodeIterator.java index 904537b00d..860694d41c 100644 --- a/group17/785396327/4.5/iterator/ByteCodeIterator.java +++ b/group17/785396327/4.5/iterator/ByteCodeIterator.java @@ -1,6 +1,5 @@ package iterator; -import org.junit.Test; import util.Util; import java.util.Arrays; @@ -47,4 +46,10 @@ public byte[] nextLengthBytes(int length) { codes = Arrays.copyOfRange(codes, length, codes.length); return result; } + + public int nextU4ToInt() { + byte[] buff = new byte[]{codes[0], codes[1], codes[2], codes[3]}; + codes = Arrays.copyOfRange(codes, 4, codes.length); + return Util.byteToInt(buff); + } } diff --git a/group17/785396327/4.5/parse/ClassFilePaser.java b/group17/785396327/4.5/parse/ClassFilePaser.java index 4e3053e78f..eb6514f449 100644 --- a/group17/785396327/4.5/parse/ClassFilePaser.java +++ b/group17/785396327/4.5/parse/ClassFilePaser.java @@ -5,11 +5,15 @@ import clz.ClassIndex; import com.sun.corba.se.impl.orbutil.closure.Constant; import constant.*; +import field.Field; import iterator.ByteCodeIterator; +import method.Method; import util.Util; +import java.util.List; + /** - * Created by IBM on 2017/4/11. + * Created by william on 2017/4/11. */ public class ClassFilePaser { private ClassFile classFile; @@ -33,9 +37,31 @@ public ClassFile parse(byte[] codes) { ClassIndex classIndex = parseClassIndex(iterator); classFile.setClassIndex(classIndex); + + iterator.nextU2ToInt();//没有接口直接读取两个字节 + + int fieldCount = iterator.nextU2ToInt(); + for (int i = 0; i < fieldCount; i++) { + Field field = parseField(iterator, constantPool); + classFile.addField(field); + } + + int methodCount = iterator.nextU2ToInt(); + for (int i = 0; i < methodCount; i++) { + Method method = parseMethod(iterator, classFile); + classFile.addMethod(method); + } return classFile; } + private Method parseMethod(ByteCodeIterator iterator, ClassFile classFile) { + return Method.parse(classFile,iterator); + } + + private Field parseField(ByteCodeIterator iterator, ConstantPool constantPool) { + return Field.parse(constantPool, iterator); + } + private ClassIndex parseClassIndex(ByteCodeIterator iterator) { ClassIndex classIndex = new ClassIndex(); classIndex.setThisClassIndex(iterator.nextU2ToInt()); diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index f1361b07a0..8aacc9ee57 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -19,7 +19,7 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "jvm_1/EmployeeV1"; - static String path1 = "G:\\Git\\homework\\coding2017\\group17\\785396327\\3.12\\out\\production\\785396327"; + static String path1 = "G:\\Git\\homework\\coding2017\\group17\\785396327\\out\\production\\785396327"; static String path2 = "C:\temp"; static ClassFile clzFile = null; @@ -29,7 +29,7 @@ public class ClassFileloaderTest { String className = "jvm_1.EmployeeV1"; clzFile = loader.loadClass(className); -// clzFile.print(); + clzFile.print(); } diff --git a/group17/785396327/4.9/attr/CodeAttr.java b/group17/785396327/4.9/attr/CodeAttr.java index b069203d4f..bfa3eeacc8 100644 --- a/group17/785396327/4.9/attr/CodeAttr.java +++ b/group17/785396327/4.9/attr/CodeAttr.java @@ -1,6 +1,7 @@ package attr; import clz.ClassFile; +import constant.ConstantInfo; import iterator.ByteCodeIterator; /** @@ -42,9 +43,33 @@ public void setLocalVariableTable(LocalVariableTable t) { } public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { - - - return null; + //按照属性表格式读取 + int attributeNameIndex = iter.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLength = iter.nextU4ToInt(); + byte[] code = iter.nextLengthBytes(codeLength); + int exceptionTableLength = iter.nextU2ToInt();//跳过异常表 + System.out.println("Code属性表中的异常表元素大小:" + exceptionTableLength); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, new String(code)); + int attributesCount = iter.nextU2ToInt(); + //code属性表中又有属性 + for (int i = 0; i < attributesCount; i++) { + int attrIndex = iter.nextU2ToInt(); + String utf8String = clzFile.getConstantPool().getUTF8String(attrIndex); +// clzFile.getConstantPool().getConstantInfo(attrIndex). + if ("LineNumberTable".equals(utf8String)) { + codeAttr.setLineNumberTable(LineNumberTable.parse(iter)); + } else if ("LocalVariableTable".equals(utf8String)) { + codeAttr.setLocalVariableTable(LocalVariableTable.parse(iter)); + } else if ("stackMapTable".equals(utf8String)) { + codeAttr.setStackMapTable(StackMapTable.parse(iter)); + } else { + throw new RuntimeException("other attribute in code table"); + } + } + return codeAttr; } private void setStackMapTable(StackMapTable t) { diff --git a/group17/785396327/4.9/attr/LineNumberTable.java b/group17/785396327/4.9/attr/LineNumberTable.java index f875aa2427..0b857f4e0f 100644 --- a/group17/785396327/4.9/attr/LineNumberTable.java +++ b/group17/785396327/4.9/attr/LineNumberTable.java @@ -6,7 +6,7 @@ import java.util.List; /** - * Created by IBM on 2017/4/12. + * Created by william on 2017/4/12. */ public class LineNumberTable extends AttributeInfo { List items = new ArrayList(); @@ -35,9 +35,20 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } - public static LineNumberTable parse(ByteCodeIterator iter){ - - return null; + public static LineNumberTable parse(ByteCodeIterator iter) { + int attributeNameIndex = iter.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + int lineNumberTableLength = iter.nextU2ToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex,attributeLength); + for (int i = 0; i < lineNumberTableLength; i++) { + int start_pc = iter.nextU2ToInt(); + int lineNumber = iter.nextU2ToInt(); + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setLineNum(lineNumber); + lineNumberItem.setStartPC(start_pc); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; } diff --git a/group17/785396327/4.9/attr/LocalVariableTable.java b/group17/785396327/4.9/attr/LocalVariableTable.java index 060ed31e85..83d21a883e 100644 --- a/group17/785396327/4.9/attr/LocalVariableTable.java +++ b/group17/785396327/4.9/attr/LocalVariableTable.java @@ -16,8 +16,25 @@ public LocalVariableTable(int attrNameIndex, int attrLen) { } public static LocalVariableTable parse(ByteCodeIterator iter) { - - return null; + int attributeNameIndex = iter.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + int localVariableTableLength = iter.nextU2ToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex, attributeLength); + for (int i = 0; i < localVariableTableLength; i++) { + int startPc = iter.nextU2ToInt(); + int length = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int index = iter.nextU2ToInt(); + LocalVariableItem localVariableItem = new LocalVariableItem(); + localVariableItem.setStartPC(startPc); + localVariableItem.setLength(length); + localVariableItem.setNameIndex(nameIndex); + localVariableItem.setDescIndex(descIndex); + localVariableItem.setIndex(index); + localVariableTable.addLocalVariableItem(localVariableItem); + } + return localVariableTable; } private void addLocalVariableItem(LocalVariableItem item) { diff --git a/group17/785396327/4.9/field/Field.java b/group17/785396327/4.9/field/Field.java index 896398d113..dda04d2d4b 100644 --- a/group17/785396327/4.9/field/Field.java +++ b/group17/785396327/4.9/field/Field.java @@ -12,10 +12,9 @@ public class Field { private int descriptorIndex; - private ConstantPool pool; - public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { this.accessFlag = accessFlag; this.nameIndex = nameIndex; @@ -24,10 +23,19 @@ public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool po } + public static Field parse(ConstantPool pool, ByteCodeIterator iter) { + int accessFlags = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptor_index = iter.nextU2ToInt(); + int attributesCount = iter.nextU2ToInt(); + if (attributesCount > 0) { + throw new RuntimeException("Field字段表,暂时不支持存在属性"); + } + return new Field(accessFlags, nameIndex, descriptor_index, pool); + } - - public static Field parse(ConstantPool pool, ByteCodeIterator iter){ - - return null; + @Override + public String toString() { + return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex); } } diff --git a/group17/785396327/4.9/method/Method.java b/group17/785396327/4.9/method/Method.java index f3b51fd15d..c0836c8bdc 100644 --- a/group17/785396327/4.9/method/Method.java +++ b/group17/785396327/4.9/method/Method.java @@ -3,6 +3,7 @@ import attr.CodeAttr; import clz.ClassFile; import iterator.ByteCodeIterator; +import util.Util; /** * Created by IBM on 2017/4/12. @@ -46,7 +47,16 @@ public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIn public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { - return null; + int accessFlags = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attributesCount = iter.nextU2ToInt();//有几个属性 + Method method = new Method(clzFile, accessFlags, nameIndex, descriptorIndex); + for (int i = 0; i < attributesCount; i++) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.codeAttr = codeAttr; + } + return new Method(clzFile, accessFlags, nameIndex, descriptorIndex); } } From 62cd9d89adfc6352923d1a227c713a0dc8518f9c Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Thu, 13 Apr 2017 19:00:07 +0800 Subject: [PATCH 022/151] homework 17/4/13 parse for method and field ,didn't completed --- .../coderising/jvm/attr/AttributeInfo.java | 7 + .../coderising/jvm/attr/LineNumberTable.java | 10 ++ .../jvm/attr/LocalVariableItem.java | 10 ++ .../jvm/attr/LocalVariableTable.java | 10 ++ .../coderising/jvm/attr/StackMapTable.java | 10 ++ .../com/coderising/jvm/clz/ClassFile.java | 41 ++--- .../coderising/jvm/constant/ClassInfo.java | 25 +++- .../coderising/jvm/constant/ConstantInfo.java | 5 + .../coderising/jvm/constant/ConstantPool.java | 25 ++-- .../coderising/jvm/constant/DoubleInfo.java | 4 + .../coderising/jvm/constant/FieldRefInfo.java | 50 ++++--- .../coderising/jvm/constant/FloatInfo.java | 5 + .../coderising/jvm/constant/IntegerInfo.java | 5 + .../com/coderising/jvm/constant/LongInfo.java | 5 + .../jvm/constant/MethodRefInfo.java | 59 +++++--- .../jvm/constant/NameAndTypeInfo.java | 49 +++--- .../jvm/constant/NullConstantInfo.java | 4 + .../coderising/jvm/constant/StringInfo.java | 36 +++-- .../com/coderising/jvm/constant/UTF8Info.java | 36 +++-- .../java/com/coderising/jvm/field/Field.java | 75 ++++++++-- .../jvm/loader/ByteCodeIterator.java | 7 + .../jvm/loader/ClassFileParser.java | 140 ++++++++++++------ .../com/coderising/jvm/method/Method.java | 66 +++++++-- .../java/com/coderising/jvm/util/Util.java | 3 + .../jvm/loader/ClassFileLoaderTest.java | 2 +- 25 files changed, 506 insertions(+), 183 deletions(-) create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java index 11e25039c3..a4d82c25c9 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java @@ -1,5 +1,8 @@ package com.coderising.jvm.attr; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + public abstract class AttributeInfo { public static final String CODE = "Code"; public static final String CONST_VALUE = "ConstantValue"; @@ -15,4 +18,8 @@ public AttributeInfo(int attrNameIndex, int attrLen) { this.attrNameIndex = attrNameIndex; this.attrLen = attrLen; } + + public static AttributeInfo parse(ConstantPool cp, ByteCodeIterator itr){ + throw new RuntimeException("AttributeInfo parse hasn't implemented"); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..cccbce87b5 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.attr; + +public class LineNumberTable extends AttributeInfo { + + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + // TODO Auto-generated constructor stub + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..74ca8df92e --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.attr; + +public class LocalVariableItem extends AttributeInfo { + + public LocalVariableItem(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + // TODO Auto-generated constructor stub + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..2a3af25d77 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.attr; + +public class LocalVariableTable extends AttributeInfo { + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + // TODO Auto-generated constructor stub + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..525d6a9071 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.attr; + +public class StackMapTable extends AttributeInfo{ + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + // TODO Auto-generated constructor stub + } + +} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java index fee1cc2415..7460b4953b 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/clz/ClassFile.java @@ -17,31 +17,38 @@ public class ClassFile { private ConstantPool pool; private List fields = new ArrayList(); private List methods = new ArrayList(); - - public void print(){ - - if(this.accessFlag.isPublicClass()){ + + 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()); - + System.out.println("Class Name:" + getClassName()); + + System.out.println("Super Class Name:" + getSuperClassName()); } - public String getClassName(){ + public String getClassName() { int index = this.clzIndex.getThisClassIndex(); - ClassInfo c = (ClassInfo)pool.getConstantInfo(index); + ClassInfo c = (ClassInfo) pool.getConstantInfo(index); return c.getClassName(); } - public String getSuperClassName(){ + + public String getSuperClassName() { int index = this.clzIndex.getSuperClassIndex(); - ClassInfo c = (ClassInfo)pool.getConstantInfo(index); + ClassInfo c = (ClassInfo) pool.getConstantInfo(index); return c.getClassName(); } + + public void addFields(Field f) { + this.fields.add(f); + } + + public void addMethods(Method m) { + this.methods.add(m); + } + /* * getter setter - * */ public int getMinorVersion() { return minorVersion; @@ -87,16 +94,16 @@ public List getFields() { return fields; } - public void addFields(Field f){ - this.fields.add(f); + public void setFields(List fl) { + this.fields = fl; } public List getMethods() { return methods; } - public void addMethods(Method m){ - this.methods.add(m); + public void setMethods(List ml) { + this.methods = ml; } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java index 772ec3f1e0..8758755887 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ClassInfo.java @@ -4,17 +4,19 @@ public class ClassInfo extends ConstantInfo { private int type = CLASS_INFO;// u1 tag private int utf8Index;// u2 name_index + public ClassInfo(ConstantPool c) { + super(c); + } + @Override public int getType() { return type; } - public int getUtf8Index() { - return utf8Index; - } - - public void setUtf8Index(int name_index) { - this.utf8Index = name_index; + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " ClassInfo" + + ",u2 name_index:" + getUtf8Index()); } public String getClassName() { @@ -23,4 +25,15 @@ public String getClassName() { .getConstantInfo(name_index); return utf8.getValue(); } + + /* + * getter setter + */ + public int getUtf8Index() { + return utf8Index; + } + + public void setUtf8Index(int name_index) { + this.utf8Index = name_index; + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java index 885fba98b5..a485aa25f9 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantInfo.java @@ -22,6 +22,11 @@ public ConstantInfo(ConstantPool cp){ public abstract int getType(); + public abstract void print(); + + /* + * getter setter + */ public ConstantPool getConstantPool(){ return this.constantPool; } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java index 009b2c45c4..c1239d9220 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/ConstantPool.java @@ -5,7 +5,6 @@ public class ConstantPool { private List cl = new ArrayList(); - private int constantPoolSize; public void addConstantInfo(ConstantInfo e){ cl.add(e); @@ -18,18 +17,22 @@ public ConstantInfo getConstantInfo(int index) { public int getSize() { return cl.size() - 1;// 减去常量池的长度一项 } - /* - * getter setter - */ - public int getConstantPoolSize() { - return constantPoolSize; - } - - public void setConstantPoolSize(int constantPoolSize) { - this.constantPoolSize = constantPoolSize; - } public String getUTF8String(int nameIndex) { return ((UTF8Info)getConstantInfo(nameIndex)).getValue(); } + + public String print(){ + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < cl.size(); i++) { + ConstantInfo c = cl.get(i); + if(i<10){ + System.out.print("0"+i+". "); + }else{ + System.out.print(i+". "); + } + c.print(); + } + return sb.toString(); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java index 9d6112ee35..25a0628678 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/DoubleInfo.java @@ -7,4 +7,8 @@ public class DoubleInfo extends ConstantInfo { public int getType() { return type; } + @Override + public void print() { + + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java index 8d3a8c25c8..3170fa25d1 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java @@ -1,34 +1,29 @@ package com.coderising.jvm.constant; public class FieldRefInfo extends ConstantInfo { - private int type = FIELD_INFO;//u1 tag - private int class_index;//u2 class_index - private int name_and_type_index;//u2 name_and_type_index + private int type = FIELD_INFO;// u1 tag + private int class_index;// u2 class_index + private int name_and_type_index;// u2 name_and_type_index + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } @Override public int getType() { return type; } - public int getClass_index() { - return class_index; - } - - public void setClass_index(int class_index) { - this.class_index = class_index; - } - - public int getName_and_type_index() { - return name_and_type_index; - } - - public void setName_and_type_index(int name_and_type_index) { - this.name_and_type_index = name_and_type_index; + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " FieldInfo" + + ",u2 class_index:" + getClass_index() + + ",u2 name_and_type_index:" + getName_and_type_index()); } @Override public String toString() { - return getClassName() + ":"+getFieldName()+" : "+getFieldType(); + return getClassName() + ":" + getFieldName() + " : " + getFieldType(); } public String getClassName() { @@ -49,4 +44,23 @@ public String getFieldType() { return nameAndTypeInfo.getTypeInfo(); } + /* + * getter setter + */ + public int getClass_index() { + return class_index; + } + + public void setClass_index(int class_index) { + this.class_index = class_index; + } + + public int getName_and_type_index() { + return name_and_type_index; + } + + public void setName_and_type_index(int name_and_type_index) { + this.name_and_type_index = name_and_type_index; + } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java index d02f37f6d8..c20ebee388 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/FloatInfo.java @@ -7,4 +7,9 @@ public class FloatInfo extends ConstantInfo { public int getType() { return type; } + @Override + public void print() { + // TODO Auto-generated method stub + + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java index b89a8925c4..35da3f20ef 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/IntegerInfo.java @@ -8,6 +8,11 @@ public class IntegerInfo extends ConstantInfo { public int getType() { return type; } + @Override + public void print() { + // TODO Auto-generated method stub + + } public int getNum() { return Num; diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java index 23c80a2640..61a19f320c 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/LongInfo.java @@ -7,4 +7,9 @@ public class LongInfo extends ConstantInfo { public int getType() { return type; } + @Override + public void print() { + // TODO Auto-generated method stub + + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java index 4064e09b39..ad59210e84 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java @@ -1,29 +1,12 @@ package com.coderising.jvm.constant; public class MethodRefInfo extends ConstantInfo { - private int type = METHOD_INFO;//u1 tag - private int classInfoIndex;//u2 class_index - private int nameAndTypeIndex;//u2 name_and_type_index + private int type = METHOD_INFO;// u1 tag + private int classInfoIndex;// u2 class_index + private int nameAndTypeIndex;// u2 name_and_type_index - @Override - public int getType() { - return type; - } - - public int getClassInfoIndex() { - return classInfoIndex; - } - - public void setClassInfoIndex(int class_index) { - this.classInfoIndex = class_index; - } - - public int getNameAndTypeIndex() { - return nameAndTypeIndex; - } - - public void setNameAndTypeIndex(int name_and_type_index) { - this.nameAndTypeIndex = name_and_type_index; + public MethodRefInfo(ConstantPool pool) { + super(pool); } public String getClassName() { @@ -44,9 +27,41 @@ public String getParamsAndReturnType() { return nt.getTypeInfo(); } + @Override + public int getType() { + return type; + } + + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " MethodInfo" + + ",u2 class_index:" + getClassInfoIndex() + + ",u2 name_and_type_index" + getNameAndTypeIndex()); + } + @Override public String toString() { return getClassName() + ":" + getMethodName() + ":" + getParamsAndReturnType(); } + + /* + * getter setter + */ + public int getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int class_index) { + this.classInfoIndex = class_index; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int name_and_type_index) { + this.nameAndTypeIndex = name_and_type_index; + } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java index 61b434d245..08e9b6a0f2 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -2,14 +2,44 @@ public class NameAndTypeInfo extends ConstantInfo { private int type = NAME_AND_TYPE_INFO;// u1 tag - private int name_index;//u2 name_index - private int descriptor_index;//u2 descriptor_index + private int name_index;// u2 name_index + private int descriptor_index;// u2 descriptor_index + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } @Override public int getType() { return type; } + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " NameAndTypeInfo" + + ",u2 name_index:" + getName_index() + ",u2 descriptor_index:" + + getDescriptor_index()); + } + + @Override + public String toString() { + return "(" + getName() + "," + getTypeInfo() + ")"; + } + + public String getName() { + UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(name_index); + return u.getValue(); + } + + public String getTypeInfo() { + UTF8Info u = (UTF8Info) this.constantPool + .getConstantInfo(descriptor_index); + return u.getValue(); + } + + /* + * getter setter + */ public int getName_index() { return name_index; } @@ -25,19 +55,4 @@ public int getDescriptor_index() { public void setDescriptor_index(int descriptor_index) { this.descriptor_index = descriptor_index; } - - public String getName() { - UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(name_index); - return u.getValue(); - } - - public String getTypeInfo() { - UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(descriptor_index); - return u.getValue(); - } - - @Override - public String toString() { - return "(" + getName() + "," + getTypeInfo() + ")"; - } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java index b383988fe7..2c67e88d37 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java @@ -6,5 +6,9 @@ public class NullConstantInfo extends ConstantInfo{ public int getType() { return -1; } + @Override + public void print() { + System.out.println("NullConstantInfo"); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java index b2bbbe9093..4fac07f7cc 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/StringInfo.java @@ -1,25 +1,43 @@ package com.coderising.jvm.constant; public class StringInfo extends ConstantInfo { - private int type = STRING_INFO;//u1 tag - private int string_index;//u2 string_index + private int type = STRING_INFO;// u1 tag + private int string_index;// u2 string_index + + public StringInfo(ConstantPool cp) { + super(cp); + } + @Override public int getType() { return type; } - public int getString_index() { - return string_index; - } - public void setString_index(int string_index) { - this.string_index = string_index; + + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " StringInfo" + + ",u2 string_index:" + getString_index()); } - public String getString(){ - UTF8Info u = (UTF8Info)this.constantPool.getConstantInfo(string_index); + + public String getString() { + UTF8Info u = (UTF8Info) this.constantPool.getConstantInfo(string_index); return u.getValue(); } + @Override public String toString() { return getString(); } + /* + * getter setter + */ + public int getString_index() { + return string_index; + } + + public void setString_index(int string_index) { + this.string_index = string_index; + } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java index 4bcf998504..ef5eef58a2 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/constant/UTF8Info.java @@ -1,31 +1,47 @@ package com.coderising.jvm.constant; public class UTF8Info extends ConstantInfo { - private int type = UTF8_INFO;//u1 tag - private int length;//u2 length - private String value;//n 个 u1 + private int type = UTF8_INFO;// u1 tag + private int length;// u2 length + private String value;// n 个 u1 + public UTF8Info(ConstantPool pool) { super(pool); } + @Override public int getType() { return type; } - public int getLength() { - return length; + + @Override + public void print() { + System.out.println("u1 tag:" + getType() + " UTF8Info" + ",u2 length:" + + getLength() + ",u1 bytes[" + getLength() + "] " + getValue()); } - public void setLength(int length) { - this.length = length; + + @Override + public String toString() { + return "UTF8Info [type=" + type + ",length=" + length + ",value=" + + value + "]"; } + + /* + * getter setter + */ public String getValue() { return value; } + public void setValue(String value) { this.value = value; } - @Override - public String toString() { - return "UTF8Info [type="+type+",length="+length+",value="+value+"]"; + + public int getLength() { + return length; } + public void setLength(int length) { + this.length = length; + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java index 19fcec9e46..f28d2d6140 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java @@ -1,29 +1,60 @@ package com.coderising.jvm.field; +import java.util.List; + +import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; public class Field { - private int accessFlag;//u2 access_flags - private int nameIndex;//u2 name_index - private int descriptorIndex;//u2 descriptor_index - //attr 属性表信息首次写jvm先放弃,以后再加 - - private ConstantPool pool; - - public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { - + private int accessFlag;// u2 access_flags + private int nameIndex;// u2 name_index + private int descriptorIndex;// u2 descriptor_index + private int attrCount;//u2 attributes_count + private List attributeInfos;//attribute_info attributes[attributes_count]; + + public Field(){} + public Field(int accessFlag, int nameIndex, int descriptorIndex, + int attrCount) { + super(); this.accessFlag = accessFlag; this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; - this.pool = pool; + this.attrCount = attrCount; + } + + /** + * 读取字段
+ * field_info {
+ * u2 access_flags,
+ * u2 name_index,
+ * u2 descriptor_index,
+ * u2 attributes_count,
+ * attribute_info attributes[attributes_count]
+ * } + * + * @param itr + * @return Field + */ + public static Field parse(ConstantPool pool, ByteCodeIterator itr) { + int accessFlag = itr.nextU2toInt(); + int nameIndex = itr.nextU2toInt(); + int descriptorIndex = itr.nextU2toInt(); + int attrCount = itr.nextU2toInt(); + Field field = new Field(accessFlag, nameIndex, descriptorIndex, attrCount); + for (int i = 0; i < attrCount; i++) { + field.addAttributeInfo(AttributeInfo.parse(pool, itr)); + } + return field; } - public static Field parse(ConstantPool pool,ByteCodeIterator iter){ - - return null; + public void addAttributeInfo(AttributeInfo a) { + this.attributeInfos.add(a); } + /* + * getter setter + */ public int getAccessFlag() { return accessFlag; } @@ -47,5 +78,21 @@ public int getDescriptorIndex() { public void setDescriptorIndex(int descriptorIndex) { this.descriptorIndex = descriptorIndex; } - + + public int getAttrCount() { + return attrCount; + } + + public void setAttrCount(int attrCount) { + this.attrCount = attrCount; + } + + public List getAttributeInfos() { + return attributeInfos; + } + + public void setAttributeInfos(List attributeInfos) { + this.attributeInfos = attributeInfos; + } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java index 7bd30d2832..5cdf37fdaf 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java @@ -38,4 +38,11 @@ public String nextUxtoHexString(int len) { } return Util.byteToHexString(bytes); } + public String nextUxtoAscii(int len){ + byte[] bytes = new byte[len]; + for (int i = 0; i < len; i++) { + bytes[i] = codes[pos++]; + } + return Util.byteToAscii(bytes); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java index 87f748c2d0..90ae51a12c 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java @@ -1,5 +1,7 @@ package com.coderising.jvm.loader; +import java.util.List; + import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; @@ -13,36 +15,62 @@ import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFileParser { /** * 读取ClassFile对象 + * * @param codes * @return */ public ClassFile parse(byte[] codes) { ClassFile cf = new ClassFile(); ByteCodeIterator itr = new ByteCodeIterator(codes); - String magicNumber = itr.nextUxtoHexString(4);//1读取魔数 + String magicNumber = itr.nextUxtoHexString(4);// 1读取魔数 if (!magicNumber.equals("cafebabe")) { throw new RuntimeException("magicNum not ok"); } - cf.setMajorVersion(itr.nextU2toInt());//2读取主版本号 - cf.setMinorVersion(itr.nextU2toInt());//3读取次版本号 + cf.setMinorVersion(itr.nextU2toInt());// 3读取次版本号 + cf.setMajorVersion(itr.nextU2toInt());// 2读取主版本号 - ConstantPool pool = parseConstantPool(itr);//4、5读取常量池 + ConstantPool pool = parseConstantPool(itr);// 4、5读取常量池 + pool.print();// 打印常量池 cf.setPool(pool); - - cf.setAccessFlag(new AccessFlag(itr.nextU2toInt()));//6读取访问标志 - - ClassIndex classIndex = parseClassIndex(itr);//读取类引用7this和8super + + cf.setAccessFlag(new AccessFlag(itr.nextU2toInt()));// 6读取访问标志 + + ClassIndex classIndex = parseClassIndex(itr);// 读取类引用7this和8super cf.setClzIndex(classIndex); - + + int interfaceCount = itr.nextU2toInt();//读取接口信息 + if (interfaceCount != 0) { + throw new RuntimeException( + "the interface isn't 0,parser has not been implemented yet."); + } + + int FieldCount = itr.nextU2toInt();//读取字段信息 + for (int i = 0; i < FieldCount; i++) { + Field f = Field.parse(pool, itr); + cf.addFields(f); + } + + int MethodCount = itr.nextU2toInt(); + for (int i = 0; i < MethodCount; i++) {//读取方法信息 + Method m = Method.parse(pool, itr); + cf.addMethods(m); + } + return cf; } /** - * 读取this super对象引用 + * 读取this super对象引用
+ * classIndex_Info {
+ * u2 this_class,
+ * u2 super_class
+ * } + * * @param itr * @return */ @@ -52,74 +80,111 @@ public ClassIndex parseClassIndex(ByteCodeIterator itr) { classIndex.setSuperClassIndex(itr.nextU2toInt()); return classIndex; } + /** * 读取常量池 + * * @param itr * @return */ public ConstantPool parseConstantPool(ByteCodeIterator itr) { int count = itr.nextU2toInt(); ConstantPool pool = new ConstantPool(); - pool.setConstantPoolSize(count);; pool.addConstantInfo(new NullConstantInfo());// 占住常量池的第一个,常量池是的index从1开始 for (int i = 1; i < count; i++) { int tag = itr.nextU1toInt(); switch (tag) { case ConstantInfo.CLASS_INFO: - ClassInfo classInfo = new ClassInfo(); + ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(itr.nextU2toInt()); pool.addConstantInfo(classInfo); + + /* + * System.out.println(i + ". u1 tag:" + + * classInfo.getType()+" ClassInfo" + ",u2 name_index:" + + * classInfo.getUtf8Index()); + */ break; case ConstantInfo.UTF8_INFO: UTF8Info utf8Info = new UTF8Info(pool); int length = itr.nextU2toInt(); - String value = itr.nextUxtoHexString(length); + String value = itr.nextUxtoAscii(length); utf8Info.setLength(length); utf8Info.setValue(value); pool.addConstantInfo(utf8Info); + + /* + * System.out.println(i + ". u1 tag:" + utf8Info.getType() + + * " UTF8Info" + ",u2 length:" + utf8Info.getLength() + + * ",u1 bytes[" + utf8Info.getLength() + "] " + + * utf8Info.getValue()); + */ break; case ConstantInfo.STRING_INFO: - StringInfo si = new StringInfo(); + StringInfo si = new StringInfo(pool); si.setString_index(itr.nextU2toInt()); pool.addConstantInfo(si); + + /* + * System.out.println(i + ". u1 tag:" + + * si.getType()+" StringInfo" + ",u2 string_index:" + + * si.getString_index()); + */ break; case ConstantInfo.NAME_AND_TYPE_INFO: - NameAndTypeInfo nt = new NameAndTypeInfo(); + NameAndTypeInfo nt = new NameAndTypeInfo(pool); nt.setName_index(itr.nextU2toInt()); nt.setDescriptor_index(itr.nextU2toInt()); pool.addConstantInfo(nt); + + /* + * System.out.println(i + ". u1 tag:" + nt.getType()+ + * " NameAndTypeInfo" + ",u2 name_index:" + nt.getName_index() + + * ",u2 descriptor_index:" + nt.getDescriptor_index()); + */ break; case ConstantInfo.METHOD_INFO: - MethodRefInfo m = new MethodRefInfo(); + MethodRefInfo m = new MethodRefInfo(pool); m.setClassInfoIndex(itr.nextU2toInt()); m.setNameAndTypeIndex(itr.nextU2toInt()); pool.addConstantInfo(m); + + /* + * System.out.println(i + ". u1 tag:" + m.getType()+ + * " MethodInfo" + ",u2 class_index:" + m.getClassInfoIndex() + + * ",u2 name_and_type_index" + m.getNameAndTypeIndex()); + */ break; case ConstantInfo.FIELD_INFO: - FieldRefInfo f = new FieldRefInfo(); + FieldRefInfo f = new FieldRefInfo(pool); f.setClass_index(itr.nextU2toInt()); f.setName_and_type_index(itr.nextU2toInt()); pool.addConstantInfo(f); - break; - /*case ConstantInfo.FLOAT_INFO: - - break; - - case ConstantInfo.INTEGER_INFO: - break; - - case ConstantInfo.DOUBLE_INFO: + /* + * System.out.println(i + ". u1 tag:" + f.getType()+ + * " FieldInfo" + ",u2 class_index:" + f.getClass_index() + + * ",u2 name_and_type_index:" + f.getName_and_type_index()); + */ break; - case ConstantInfo.LONG_INFO: - break;*/ + /* + * case ConstantInfo.FLOAT_INFO: + * + * break; + * + * case ConstantInfo.INTEGER_INFO: break; + * + * case ConstantInfo.DOUBLE_INFO: break; + * + * case ConstantInfo.LONG_INFO: break; + */ default: throw new RuntimeException("the constant pool tag " + tag @@ -128,22 +193,5 @@ public ConstantPool parseConstantPool(ByteCodeIterator itr) { } return pool; } - /** - * 读取字段 - * @param itr - * @return - */ - public Field parseField(ByteCodeIterator itr){ - - return null; - } - /** - * 读取方法 - * @param itr - * @return - */ - public Field parseMethod(ByteCodeIterator itr){ - - return null; - } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java index 456e5d9f94..04b0df7c3c 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java @@ -1,45 +1,87 @@ package com.coderising.jvm.method; -import com.coderising.jvm.attr.CodeAttr; +import java.util.List; + +import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; public class Method { - private int accessFlag; - private int nameIndex; - private int descriptorIndex; - - private CodeAttr codeAttr; - + private int accessFlag;// u2 access_flags + private int nameIndex;// u2 name_index + private int descriptorIndex;// u2 descriptor_index + private int attrCount;//u2 attributes_count + private List attributeInfos;//attribute_info attributes[attributes_count]; + private ClassFile clzFile; + + /** + * 读取方法 method_info {
+ * u2 access_flags,
+ * u2 name_index,
+ * u2 descriptor_index,
+ * u2 attributes_count,
+ * attribute_info attributes[attributes_count]
+ * } + * + * @param itr + * @return + */ + public static Method parse(ConstantPool cp, ByteCodeIterator itr) { + int accessFlag = itr.nextU2toInt(); + int nameIndex= itr.nextU2toInt(); + int descriptorIndex = itr.nextU2toInt(); + int attrCount = itr.nextU2toInt(); + + return null; + } + /* * getter setter */ public int getAccessFlag() { return accessFlag; } + public void setAccessFlag(int accessFlag) { this.accessFlag = accessFlag; } + public int getNameIndex() { return nameIndex; } + public void setNameIndex(int nameIndex) { this.nameIndex = nameIndex; } + public int getDescriptorIndex() { return descriptorIndex; } + public void setDescriptorIndex(int descriptorIndex) { this.descriptorIndex = descriptorIndex; } - public CodeAttr getCodeAttr() { - return codeAttr; + + public List getAttributeInfos() { + return attributeInfos; } - public void setCodeAttr(CodeAttr codeAttr) { - this.codeAttr = codeAttr; + + public void setAttributeInfos(List attributeInfos) { + this.attributeInfos = attributeInfos; } + public ClassFile getClzFile() { return clzFile; } - + + public int getAttrCount() { + return attrCount; + } + + public void setAttrCount(int attrCount) { + this.attrCount = attrCount; + } + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java index 2201593cd2..c69ba73610 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/util/Util.java @@ -18,4 +18,7 @@ public static String byteToHexString(byte[] codes) { } return buffer.toString(); } + public static String byteToAscii(byte[] codes){ + return new String(codes); + } } diff --git a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java index 194db3cba0..da5ab5f0a7 100644 --- a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java +++ b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java @@ -81,7 +81,7 @@ public void testMagicNumber(){ @Test public void testVersion(){ Assert.assertEquals(0, clzFile.getMinorVersion()); - Assert.assertEquals(52, clzFile.getMajorVersion()); + Assert.assertEquals(51, clzFile.getMajorVersion()); } @Test From aa8a20dff826a2f4bac57be24191908cfbc5850c Mon Sep 17 00:00:00 2001 From: gongxun Date: Thu, 13 Apr 2017 21:46:42 +0800 Subject: [PATCH 023/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.9/attr/CodeAttr.java | 6 +++--- group17/785396327/4.9/attr/LineNumberTable.java | 3 +-- group17/785396327/4.9/attr/LocalVariableTable.java | 5 ++--- group17/785396327/4.9/attr/StackMapTable.java | 5 ++--- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/group17/785396327/4.9/attr/CodeAttr.java b/group17/785396327/4.9/attr/CodeAttr.java index bfa3eeacc8..b83508d876 100644 --- a/group17/785396327/4.9/attr/CodeAttr.java +++ b/group17/785396327/4.9/attr/CodeAttr.java @@ -60,11 +60,11 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { String utf8String = clzFile.getConstantPool().getUTF8String(attrIndex); // clzFile.getConstantPool().getConstantInfo(attrIndex). if ("LineNumberTable".equals(utf8String)) { - codeAttr.setLineNumberTable(LineNumberTable.parse(iter)); + codeAttr.setLineNumberTable(LineNumberTable.parse(iter, attrIndex)); } else if ("LocalVariableTable".equals(utf8String)) { - codeAttr.setLocalVariableTable(LocalVariableTable.parse(iter)); + codeAttr.setLocalVariableTable(LocalVariableTable.parse(iter, attrIndex)); } else if ("stackMapTable".equals(utf8String)) { - codeAttr.setStackMapTable(StackMapTable.parse(iter)); + codeAttr.setStackMapTable(StackMapTable.parse(iter, attrIndex)); } else { throw new RuntimeException("other attribute in code table"); } diff --git a/group17/785396327/4.9/attr/LineNumberTable.java b/group17/785396327/4.9/attr/LineNumberTable.java index 0b857f4e0f..acd781fb3e 100644 --- a/group17/785396327/4.9/attr/LineNumberTable.java +++ b/group17/785396327/4.9/attr/LineNumberTable.java @@ -35,8 +35,7 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } - public static LineNumberTable parse(ByteCodeIterator iter) { - int attributeNameIndex = iter.nextU2ToInt(); + public static LineNumberTable parse(ByteCodeIterator iter,int attributeNameIndex) { int attributeLength = iter.nextU4ToInt(); int lineNumberTableLength = iter.nextU2ToInt(); LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex,attributeLength); diff --git a/group17/785396327/4.9/attr/LocalVariableTable.java b/group17/785396327/4.9/attr/LocalVariableTable.java index 83d21a883e..9cb74c9697 100644 --- a/group17/785396327/4.9/attr/LocalVariableTable.java +++ b/group17/785396327/4.9/attr/LocalVariableTable.java @@ -6,7 +6,7 @@ import java.util.List; /** - * Created by IBM on 2017/4/12. + * Created by william on 2017/4/12. */ public class LocalVariableTable extends AttributeInfo { List items = new ArrayList(); @@ -15,8 +15,7 @@ public LocalVariableTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - public static LocalVariableTable parse(ByteCodeIterator iter) { - int attributeNameIndex = iter.nextU2ToInt(); + public static LocalVariableTable parse(ByteCodeIterator iter, int attributeNameIndex) { int attributeLength = iter.nextU4ToInt(); int localVariableTableLength = iter.nextU2ToInt(); LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex, attributeLength); diff --git a/group17/785396327/4.9/attr/StackMapTable.java b/group17/785396327/4.9/attr/StackMapTable.java index 8de15ac552..fce272fd9f 100644 --- a/group17/785396327/4.9/attr/StackMapTable.java +++ b/group17/785396327/4.9/attr/StackMapTable.java @@ -3,7 +3,7 @@ import iterator.ByteCodeIterator; /** - * Created by IBM on 2017/4/12. + * Created by william on 2017/4/12. */ public class StackMapTable extends AttributeInfo { private String originalCode; @@ -12,8 +12,7 @@ public StackMapTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - public static StackMapTable parse(ByteCodeIterator iter){ - int index = iter.nextU2ToInt(); + public static StackMapTable parse(ByteCodeIterator iter,int index){ // int len = iter.nextU4ToInt(); // StackMapTable t = new StackMapTable(index,len); From 46791de1544786ace8f24c5698c6b662056c58d9 Mon Sep 17 00:00:00 2001 From: gongxun Date: Thu, 13 Apr 2017 22:14:51 +0800 Subject: [PATCH 024/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E4=B8=AA=E4=BD=9C=E4=B8=9A=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.9/expr/InfixExpr.java | 18 +++++++ group17/785396327/4.9/expr/InfixExprTest.java | 48 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 group17/785396327/4.9/expr/InfixExpr.java create mode 100644 group17/785396327/4.9/expr/InfixExprTest.java diff --git a/group17/785396327/4.9/expr/InfixExpr.java b/group17/785396327/4.9/expr/InfixExpr.java new file mode 100644 index 0000000000..035542712b --- /dev/null +++ b/group17/785396327/4.9/expr/InfixExpr.java @@ -0,0 +1,18 @@ +package expr; + +/** + * Created by IBM on 2017/4/13. + */ +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + return 0.0f; + } + +} diff --git a/group17/785396327/4.9/expr/InfixExprTest.java b/group17/785396327/4.9/expr/InfixExprTest.java new file mode 100644 index 0000000000..91c19fe23e --- /dev/null +++ b/group17/785396327/4.9/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by IBM on 2017/4/13. + */ +public class InfixExprTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } +} From 452797faac2778644462e73be2b746e3a0c2ed7e Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 14 Apr 2017 07:51:52 +0800 Subject: [PATCH 025/151] InfixExpr DONE --- .../coding/basic/stack/StackUtil.java | 14 +-- .../coding/basic/stack/expr/InfixExpr.java | 105 +++++++++++++++++- .../basic/stack/expr/InfixExprTest.java | 11 +- .../coding/basic/stack/expr/TokenParser.java | 85 ++++++++++++++ .../src/com/coderising/jvm/method/Method.java | 2 +- 5 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 group12/382266293/coding/basic/stack/expr/TokenParser.java diff --git a/group12/382266293/coding/basic/stack/StackUtil.java b/group12/382266293/coding/basic/stack/StackUtil.java index 706bcd7033..e0beed1708 100644 --- a/group12/382266293/coding/basic/stack/StackUtil.java +++ b/group12/382266293/coding/basic/stack/StackUtil.java @@ -1,7 +1,5 @@ package stack; -import static org.junit.Assert.assertEquals; - import java.util.Objects; import java.util.Stack; @@ -10,22 +8,24 @@ public class StackUtil { /** * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param */ - public static void reverse(Stack stack) { + public static void reverse(Stack stack) { if (stack.isEmpty()) { return; } - int i = getAndRemoveLastElement(stack); + E i = getAndRemoveLastElement(stack); reverse(stack); stack.push(i); } - public static int getAndRemoveLastElement(Stack stack) { - int result = stack.pop(); + + public static E getAndRemoveLastElement(Stack stack) { + E result = stack.pop(); if (stack.isEmpty()) { return result; } else { - int last = getAndRemoveLastElement(stack); + E last = getAndRemoveLastElement(stack); stack.push(result); return last; } diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index eade1dc743..c927527029 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -1,18 +1,115 @@ package stack.expr; +import java.util.Stack; +import stack.StackUtil; + public class InfixExpr { String expr = null; - + public InfixExpr(String expr) { this.expr = expr; } - public float evaluate() { + public float evaluate() { + + TokenParser tp = new TokenParser(); + tp.parse(expr); + Stack ints = new Stack(); + Stack signs = new Stack(); + + int i1 = tp.nextInt(); + String sign1 = tp.nextSign(); + + ints.push(i1); + signs.push(sign1); + + while (tp.hasNextSign()) { + + int i2 = tp.nextInt(); + String sign2 = tp.nextSign(); + + + if (tp.hasNextInt()) { + + if (highPrioritySign(sign1) || lowPrioritySign(sign2) ) { + + i1 = ints.pop(); + sign1 = signs.pop(); + int result = calculate(i1, i2, sign1); + ints.push(result); + + } else { + + ints.push(i2); + + } + + signs.push(sign2); + sign1 = sign2; + + } + + } + + StackUtil.reverse(ints); + + while (!ints.isEmpty()) { + + int firstInt = ints.pop(); + + if (ints.isEmpty()) { + return (float) firstInt; + } + + int secInt = ints.pop(); + String sign = signs.pop(); + int result = calculate(firstInt, secInt, sign); + ints.push(result); - return 0.0f; + } + + return (float) ints.peek(); } - + private int calculate(int firstInt, int secInt, String lowsign) { + + int result; + if (lowsign.equals("+")) { + result = firstInt + secInt; + } else if (lowsign.equals("-")) { + result = firstInt - secInt; + } else if (lowsign.equals("*")) { + result = firstInt * secInt; + } else if (lowsign.equals("/")) { + result = firstInt / secInt; + } else { + throw new RuntimeException(lowsign + "is not supported yet!"); + } + + return result; + + } + private boolean lowPrioritySign(String sign) { + + if (sign.equals("+") || sign.equals("-")) { + + return true; + + } + + return false; + } + private boolean highPrioritySign(String sign) { + + if (sign.equals("*") || sign.equals("/")) { + + return true; + + } + + return false; + } + } diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index bb047629bd..ddff0c588c 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -5,7 +5,6 @@ import org.junit.Before; import org.junit.Test; - public class InfixExprTest { @Before @@ -18,7 +17,7 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { - //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + // InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); @@ -27,22 +26,22 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); Assert.assertEquals(100.0, expr.evaluate(), 0.001f); } - + { InfixExpr expr = new InfixExpr("3*20/2"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } - + { InfixExpr expr = new InfixExpr("20/2*3"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } - + { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } - + } } diff --git a/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..10402673d6 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,85 @@ +package stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingDeque; + +public class TokenParser { + + Queue intQ; + Queue signQ; + static final List signs = new ArrayList(); + { + signs.add("+"); + signs.add("-"); + signs.add("*"); + signs.add("/"); + } + + public TokenParser() { + intQ = new LinkedBlockingDeque(); + signQ = new LinkedBlockingDeque(); + } + + public void parse(String expr) { + + String[] tokens = expr.split(""); + String number = ""; + + for (int i = 0; i < tokens.length; i++) { + + String c = tokens[i]; + + if (isSign(c)) { + signQ.add(c); + if (!number.equals("")) { + int num = Integer.parseInt(number); + intQ.add(num); + number = ""; + } + } else { + number += tokens[i]; + } + + } + + if (!number.equals("")) { + int num = Integer.parseInt(number); + intQ.add(num); + } + + int intSize = intQ.size(); + if (intSize < 2 || intSize - signQ.size() > 1) { + throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); + } + + intQ.add(0); + signQ.add("+"); + + } + + private boolean isSign(String c) { + if (signs.contains(c)) { + return true; + } + return false; + } + + public int nextInt() { + return intQ.poll(); + } + + public String nextSign() { + return signQ.poll(); + } + + public boolean hasNextInt() { + return !intQ.isEmpty(); + } + + public boolean hasNextSign() { + return !signQ.isEmpty(); + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/method/Method.java b/group12/382266293/src/com/coderising/jvm/method/Method.java index b77ff6271b..705ec22792 100644 --- a/group12/382266293/src/com/coderising/jvm/method/Method.java +++ b/group12/382266293/src/com/coderising/jvm/method/Method.java @@ -29,7 +29,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ method.setCodeAttr(codeAttr); } else { - throw new RuntimeException(att_name + "has not been implemented"); + throw new RuntimeException(att_name + " has not been implemented"); } } From 452ee7278a9273a21efd203a112352a6920fa30e Mon Sep 17 00:00:00 2001 From: Mengxz Date: Fri, 14 Apr 2017 09:33:24 +0800 Subject: [PATCH 026/151] Update 20170326-20170402.md --- group17/article/20170326-20170402.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170326-20170402.md b/group17/article/20170326-20170402.md index 5df4ce08e6..0729404704 100644 --- a/group17/article/20170326-20170402.md +++ b/group17/article/20170326-20170402.md @@ -22,7 +22,7 @@ 240094626 -82427129 +82427129 http://blog.csdn.net/Walk_er/article/details/66971517 296910598 From d0aa048dec299fb814b20dbac7e6639da8e30c0d Mon Sep 17 00:00:00 2001 From: Mengxz Date: Fri, 14 Apr 2017 09:34:09 +0800 Subject: [PATCH 027/151] Update 20170402-20170409.md --- group17/article/20170402-20170409.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170402-20170409.md b/group17/article/20170402-20170409.md index 3d45ad0516..3f2e5110a7 100644 --- a/group17/article/20170402-20170409.md +++ b/group17/article/20170402-20170409.md @@ -22,7 +22,7 @@ 240094626 -82427129 +82427129 http://blog.csdn.net/Walk_er/article/details/68486226 296910598 From 2db74efb130e9b92ad27f6e67d5b4f4428458b15 Mon Sep 17 00:00:00 2001 From: gongxun Date: Fri, 14 Apr 2017 11:49:53 +0800 Subject: [PATCH 028/151] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=89=80=E6=9C=89jvm?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.5/iterator/ByteCodeIterator.java | 9 +++++++++ group17/785396327/4.5/test/ClassFileloaderTest.java | 10 +++++----- group17/785396327/4.5/util/Util.java | 2 +- group17/785396327/4.9/attr/CodeAttr.java | 6 +++--- group17/785396327/4.9/method/Method.java | 4 ++-- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/group17/785396327/4.5/iterator/ByteCodeIterator.java b/group17/785396327/4.5/iterator/ByteCodeIterator.java index 860694d41c..adfc288cc2 100644 --- a/group17/785396327/4.5/iterator/ByteCodeIterator.java +++ b/group17/785396327/4.5/iterator/ByteCodeIterator.java @@ -47,6 +47,15 @@ public byte[] nextLengthBytes(int length) { return result; } + public String nextLengthString(int length) { + byte[] result = new byte[length]; + for (int i = 0; i < length; i++) { + result[i] = codes[i]; + } + codes = Arrays.copyOfRange(codes, length, codes.length); + return Util.byteToHexString(result); + } + public int nextU4ToInt() { byte[] buff = new byte[]{codes[0], codes[1], codes[2], codes[3]}; codes = Arrays.copyOfRange(codes, 4, codes.length); diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 8aacc9ee57..854453f2bd 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -221,7 +221,7 @@ public void testMethods(){ assertMethodEquals(pool,m, "", "(Ljava/lang/String;I)V", - "2ab7000c2a2bb5000f2a1cb50011b1"); + "2ab700012a2bb500022a1cb50003b1"); } { @@ -229,7 +229,7 @@ public void testMethods(){ assertMethodEquals(pool,m, "setName", "(Ljava/lang/String;)V", - "2a2bb5000fb1"); + "2a2bb50002b1"); } { @@ -237,14 +237,14 @@ public void testMethods(){ assertMethodEquals(pool,m, "setAge", "(I)V", - "2a1bb50011b1"); + "2a1bb50003b1"); } { Method m = methods.get(3); assertMethodEquals(pool,m, "sayHello", "()V", - "b2001c1222b60024b1"); + "b200041205b60006b1"); } { @@ -252,7 +252,7 @@ public void testMethods(){ assertMethodEquals(pool,m, "main", "([Ljava/lang/String;)V", - "bb000159122b101db7002d4c2bb6002fb1"); + "bb0007591208101db700094c2bb6000ab1"); } } diff --git a/group17/785396327/4.5/util/Util.java b/group17/785396327/4.5/util/Util.java index 9b95c51ec4..e35332238c 100644 --- a/group17/785396327/4.5/util/Util.java +++ b/group17/785396327/4.5/util/Util.java @@ -1,7 +1,7 @@ package util; /** - * Created by IBM on 2017/4/10. + * Created by william on 2017/4/10. */ public class Util { public static int byteToInt(byte[] codes){ diff --git a/group17/785396327/4.9/attr/CodeAttr.java b/group17/785396327/4.9/attr/CodeAttr.java index b83508d876..9e3505eb37 100644 --- a/group17/785396327/4.9/attr/CodeAttr.java +++ b/group17/785396327/4.9/attr/CodeAttr.java @@ -49,10 +49,10 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { int maxStack = iter.nextU2ToInt(); int maxLocals = iter.nextU2ToInt(); int codeLength = iter.nextU4ToInt(); - byte[] code = iter.nextLengthBytes(codeLength); + String code = iter.nextLengthString(codeLength); int exceptionTableLength = iter.nextU2ToInt();//跳过异常表 - System.out.println("Code属性表中的异常表元素大小:" + exceptionTableLength); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, new String(code)); +// System.out.println("Code属性表中的异常表元素大小:" + exceptionTableLength); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); int attributesCount = iter.nextU2ToInt(); //code属性表中又有属性 for (int i = 0; i < attributesCount; i++) { diff --git a/group17/785396327/4.9/method/Method.java b/group17/785396327/4.9/method/Method.java index c0836c8bdc..8a5fb59e09 100644 --- a/group17/785396327/4.9/method/Method.java +++ b/group17/785396327/4.9/method/Method.java @@ -54,9 +54,9 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { Method method = new Method(clzFile, accessFlags, nameIndex, descriptorIndex); for (int i = 0; i < attributesCount; i++) { CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); - method.codeAttr = codeAttr; + method.setCodeAttr(codeAttr); } - return new Method(clzFile, accessFlags, nameIndex, descriptorIndex); + return method; } } From 10f4cdddd21630d124c244679718b6661c270464 Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Fri, 14 Apr 2017 19:11:51 +0800 Subject: [PATCH 029/151] commit to home --- .../coderising/jvm/attr/AttributeInfo.java | 26 +++- .../com/coderising/jvm/attr/CodeAttr.java | 117 +++++++++++++++++- .../coderising/jvm/attr/LineNumberTable.java | 61 ++++++++- .../jvm/attr/LocalVariableTable.java | 15 ++- .../java/com/coderising/jvm/field/Field.java | 21 +++- .../jvm/loader/ClassFileParser.java | 2 - .../com/coderising/jvm/method/Method.java | 44 ++++++- 7 files changed, 261 insertions(+), 25 deletions(-) diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java index a4d82c25c9..f39a23dcf3 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java @@ -1,6 +1,7 @@ package com.coderising.jvm.attr; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public abstract class AttributeInfo { @@ -10,16 +11,29 @@ public abstract class AttributeInfo { 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; + int attrNameIndex;// u2 attribute_name_index + int attrLen;// u4 attribute_length public AttributeInfo(int attrNameIndex, int attrLen) { - this.attrNameIndex = attrNameIndex; this.attrLen = attrLen; } - - public static AttributeInfo parse(ConstantPool cp, ByteCodeIterator itr){ - throw new RuntimeException("AttributeInfo parse hasn't implemented"); + + public static AttributeInfo parse(ConstantPool pool, ByteCodeIterator itr) { + int attrNameIndex = itr.nextU2toInt(); + String attrName = ((UTF8Info) pool.getConstantInfo(attrNameIndex)) + .getValue(); + itr.back(2); + switch (attrName) { + case CODE: + return CodeAttr.parse(pool, itr); + case LINE_NUM_TABLE: + return LineNumberTable.parse(pool, itr); + case LOCAL_VAR_TABLE: + + default: + throw new RuntimeException( + "attributeInfo exclude CodeAttr hasn't implemented"); + } } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java index a05fb3c27f..3011511ae4 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java @@ -1,14 +1,121 @@ package com.coderising.jvm.attr; -public class CodeAttr extends AttributeInfo{ +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + + private int maxStack;//u2 max_stack + private int maxLocals;//u2 max_locals + private int codeLenth;//u4 code_length + private String code;//u1 code[code_length] + private int exceptionTableLength;//u2 exception_table_length; + /* + * { u2 start_pc; + u2 end_pc; + u2 handler_pc; + u2 catch_type; + } exception_table[exception_table_length]; + private ExceptionTable exceptionTable;//unimplemented*/ + private int attrCount;//u2 attributes_count + private List AttrList = new ArrayList();//attribute_info attributes[attributes_count]; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, + int maxLocals, int codeLenth, String code, + int exceptionTableLength, int attrCount) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLenth = codeLenth; + this.code = code; + this.exceptionTableLength = exceptionTableLength; + this.attrCount = attrCount; + } + + /** + * 给CodeAttr 增加属性 + * @param a + */ + public void addAttr(AttributeInfo a){ + this.AttrList.add(a); + } + + public static CodeAttr parse(ConstantPool pool, ByteCodeIterator itr) { + int attrNameIndex = itr.nextU2toInt(); + int attrLen = itr.nextU4toInt(); + int maxStack = itr.nextU2toInt(); + int maxLocals = itr.nextU2toInt(); + int codeLenth = itr.nextU4toInt(); + String code = itr.nextUxtoHexString(codeLenth); + int exceptionTableLength = itr.nextU2toInt(); + int attrCount = itr.nextU2toInt(); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, + codeLenth, code, exceptionTableLength, attrCount); + for (int i = 0; i < attrCount; i++) { + codeAttr.addAttr(AttributeInfo.parse(pool, itr)); + } + return codeAttr; + } + /* + * getter setter + */ + public int getMaxStack() { + return maxStack; + } + + public void setMaxStack(int maxStack) { + this.maxStack = maxStack; + } + + public int getMaxLocals() { + return maxLocals; + } + + public void setMaxLocals(int maxLocals) { + this.maxLocals = maxLocals; + } + + public int getCodeLenth() { + return codeLenth; + } + + public void setCodeLenth(int codeLenth) { + this.codeLenth = codeLenth; + } + + public void setCode(String code) { + this.code = code; + } - private String code; public String getCode() { return code; } - public CodeAttr(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); - // TODO Auto-generated constructor stub + + public int getAttrCount() { + return attrCount; + } + + public void setAttrCount(int attrCount) { + this.attrCount = attrCount; + } + + public List getAttrList() { + return AttrList; + } + + public void setAttrList(List attrList) { + AttrList = attrList; + } + + public int getExceptionTableLength() { + return exceptionTableLength; + } + + public void setExceptionTableLength(int exceptionTableLength) { + this.exceptionTableLength = exceptionTableLength; } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java index cccbce87b5..30b39988f0 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java @@ -1,10 +1,67 @@ package com.coderising.jvm.attr; +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + public class LineNumberTable extends AttributeInfo { - public LineNumberTable(int attrNameIndex, int attrLen) { + private int lineNumberTableLength; + private List lineNumberTable = new ArrayList(); + + public LineNumberTable(int attrNameIndex, int attrLen, + int lineNumberTableLength) { super(attrNameIndex, attrLen); - // TODO Auto-generated constructor stub + this.lineNumberTableLength = lineNumberTableLength; + } + + public void addLineNumberItem(LineNumberItem e) { + this.lineNumberTable.add(e); + } + + public static LineNumberTable parse(ConstantPool pool, ByteCodeIterator itr) { + int attrNameIndex = itr.nextU2toInt(); + int attrLen = itr.nextU4toInt(); + int lineNumberTableLength = itr.nextU2toInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, + attrLen, lineNumberTableLength); + for (int i = 0; i < lineNumberTableLength; i++) { + lineNumberTable.addLineNumberItem(LineNumberItem.parse(pool, itr)); + } + return lineNumberTable; + } + + private static class LineNumberItem { + @SuppressWarnings("unused") + private int startPc; + @SuppressWarnings("unused") + private int lineNum; + + public LineNumberItem(int startPc, int lineNum) { + super(); + this.startPc = startPc; + this.lineNum = lineNum; + } + + public static LineNumberItem parse(ConstantPool pool, + ByteCodeIterator itr) { + int startPc = itr.nextU2toInt(); + int lineNum = itr.nextU2toInt(); + return new LineNumberTable.LineNumberItem(startPc, lineNum); + } + } + + /* + * getter setter + */ + public int getLineNumberTableLength() { + return lineNumberTableLength; + } + + public void setLineNumberTableLength(int lineNumberTableLength) { + this.lineNumberTableLength = lineNumberTableLength; } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java index 2a3af25d77..2704149043 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java @@ -2,9 +2,18 @@ public class LocalVariableTable extends AttributeInfo { - public LocalVariableTable(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); - // TODO Auto-generated constructor stub + private int localVarTableLength ;//u2 local_variable_table_length + + + private static class + /* + * getter setter + */ + public int getLocalVarTableLength() { + return localVarTableLength; + } + public void setLocalVarTableLength(int localVarTableLength) { + this.localVarTableLength = localVarTableLength; } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java index f28d2d6140..fee1d06d95 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/field/Field.java @@ -4,6 +4,7 @@ import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public class Field { @@ -12,15 +13,19 @@ public class Field { private int descriptorIndex;// u2 descriptor_index private int attrCount;//u2 attributes_count private List attributeInfos;//attribute_info attributes[attributes_count]; + + private ConstantPool cp; public Field(){} + public Field(int accessFlag, int nameIndex, int descriptorIndex, - int attrCount) { + int attrCount, ConstantPool cp) { super(); this.accessFlag = accessFlag; this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; this.attrCount = attrCount; + this.cp = cp; } /** @@ -41,7 +46,7 @@ public static Field parse(ConstantPool pool, ByteCodeIterator itr) { int nameIndex = itr.nextU2toInt(); int descriptorIndex = itr.nextU2toInt(); int attrCount = itr.nextU2toInt(); - Field field = new Field(accessFlag, nameIndex, descriptorIndex, attrCount); + Field field = new Field(accessFlag, nameIndex, descriptorIndex, attrCount, pool); for (int i = 0; i < attrCount; i++) { field.addAttributeInfo(AttributeInfo.parse(pool, itr)); } @@ -51,6 +56,12 @@ public static Field parse(ConstantPool pool, ByteCodeIterator itr) { public void addAttributeInfo(AttributeInfo a) { this.attributeInfos.add(a); } + @Override + public String toString() { + UTF8Info utf8Info1 = (UTF8Info)this.cp.getConstantInfo(this.nameIndex); + UTF8Info utf8Info2 = (UTF8Info)this.cp.getConstantInfo(this.descriptorIndex); + return utf8Info1.getValue()+":"+utf8Info2.getValue(); + } /* * getter setter @@ -94,5 +105,11 @@ public List getAttributeInfos() { public void setAttributeInfos(List attributeInfos) { this.attributeInfos = attributeInfos; } + public ConstantPool getCp() { + return cp; + } + public void setCp(ConstantPool cp) { + this.cp = cp; + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java index 90ae51a12c..b9887d3b30 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/loader/ClassFileParser.java @@ -1,7 +1,5 @@ package com.coderising.jvm.loader; -import java.util.List; - import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java index 04b0df7c3c..d29f77fb25 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java @@ -1,8 +1,10 @@ package com.coderising.jvm.method; +import java.util.ArrayList; import java.util.List; import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; @@ -11,8 +13,22 @@ public class Method { private int accessFlag;// u2 access_flags private int nameIndex;// u2 name_index private int descriptorIndex;// u2 descriptor_index - private int attrCount;//u2 attributes_count - private List attributeInfos;//attribute_info attributes[attributes_count]; + private int attrCount;// u2 attributes_count + /* + * attributes[attributes_count]; + */ + private List attributeInfos = new ArrayList(); + + public Method() {} + + public Method(int accessFlag, int nameIndex, int descriptorIndex, + int attrCount) { + super(); + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.attrCount = attrCount; + } private ClassFile clzFile; @@ -26,17 +42,35 @@ public class Method { * } * * @param itr - * @return + * @return Method */ public static Method parse(ConstantPool cp, ByteCodeIterator itr) { int accessFlag = itr.nextU2toInt(); - int nameIndex= itr.nextU2toInt(); + int nameIndex = itr.nextU2toInt(); int descriptorIndex = itr.nextU2toInt(); int attrCount = itr.nextU2toInt(); - + Method method = new Method(accessFlag, nameIndex, descriptorIndex, + attrCount); + for (int i = 0; i < attrCount; i++) { + method.addAttributeInfo(AttributeInfo.parse(cp, itr)); + } + return method; + } + + /** + * 专门用来获取code属性的方法 + * + * @return + */ + public CodeAttr getCodeAttr() { + return null; } + public void addAttributeInfo(AttributeInfo a) { + this.attributeInfos.add(a); + } + /* * getter setter */ From 721c1b63d48a72e96b9724beb1e7423dc87fa37d Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 14 Apr 2017 20:55:44 +0800 Subject: [PATCH 030/151] one bug fixed --- group12/382266293/coding/basic/stack/expr/InfixExpr.java | 5 +++-- .../382266293/coding/basic/stack/expr/InfixExprTest.java | 4 ++-- group12/382266293/coding/basic/stack/expr/TokenParser.java | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index c927527029..8bda337676 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -50,8 +50,9 @@ public float evaluate() { } } - + StackUtil.reverse(ints); + StackUtil.reverse(signs); while (!ints.isEmpty()) { @@ -83,7 +84,7 @@ private int calculate(int firstInt, int secInt, String lowsign) { } else if (lowsign.equals("/")) { result = firstInt / secInt; } else { - throw new RuntimeException(lowsign + "is not supported yet!"); + throw new RuntimeException(lowsign + "has not been supported yet!"); } return result; diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index ddff0c588c..dbb3c34f21 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -23,8 +23,8 @@ public void testEvaluate() { Assert.assertEquals(19.0, expr.evaluate(), 0.001f); } { - InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); - Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + InfixExpr expr = new InfixExpr("3*20+12*5-40/2/2+5*2*2/2+1-10/2"); + Assert.assertEquals(116.0, expr.evaluate(), 0.001f); } { diff --git a/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java index 10402673d6..2352da5e79 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParser.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -26,13 +26,15 @@ public void parse(String expr) { String[] tokens = expr.split(""); String number = ""; + String sign = ""; for (int i = 0; i < tokens.length; i++) { String c = tokens[i]; if (isSign(c)) { - signQ.add(c); + sign = c; + signQ.add(sign); if (!number.equals("")) { int num = Integer.parseInt(number); intQ.add(num); @@ -53,7 +55,7 @@ public void parse(String expr) { if (intSize < 2 || intSize - signQ.size() > 1) { throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); } - + intQ.add(0); signQ.add("+"); From 1b6f4db52f2895aac13a4be3632a66b86c90d08d Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 14 Apr 2017 21:00:03 +0800 Subject: [PATCH 031/151] 1 --- group12/382266293/coding/basic/stack/expr/InfixExpr.java | 1 + 1 file changed, 1 insertion(+) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 8bda337676..4cc73bb0bf 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -69,6 +69,7 @@ public float evaluate() { } + System.out.println("we shall not reach here"); return (float) ints.peek(); } From cddb175fb202a0cdd5175602cc529c63ee6b2b10 Mon Sep 17 00:00:00 2001 From: Admin Date: Sat, 15 Apr 2017 11:07:53 +0800 Subject: [PATCH 032/151] bug fix --- group12/382266293/coding/basic/stack/expr/InfixExpr.java | 4 ++-- group12/382266293/coding/basic/stack/expr/TokenParser.java | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 4cc73bb0bf..7b5892711b 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -50,7 +50,7 @@ public float evaluate() { } } - + StackUtil.reverse(ints); StackUtil.reverse(signs); @@ -85,7 +85,7 @@ private int calculate(int firstInt, int secInt, String lowsign) { } else if (lowsign.equals("/")) { result = firstInt / secInt; } else { - throw new RuntimeException(lowsign + "has not been supported yet!"); + throw new RuntimeException(lowsign + " has not been supported yet!"); } return result; diff --git a/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java index 2352da5e79..785be33b88 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParser.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -26,15 +26,13 @@ public void parse(String expr) { String[] tokens = expr.split(""); String number = ""; - String sign = ""; for (int i = 0; i < tokens.length; i++) { String c = tokens[i]; if (isSign(c)) { - sign = c; - signQ.add(sign); + signQ.add(c); if (!number.equals("")) { int num = Integer.parseInt(number); intQ.add(num); From 2c3e85f200785a981ec1dadfc38e711ceedca302 Mon Sep 17 00:00:00 2001 From: Admin Date: Sat, 15 Apr 2017 12:03:30 +0800 Subject: [PATCH 033/151] bug fix again --- .../coding/basic/stack/expr/InfixExpr.java | 13 ++++++++----- .../coding/basic/stack/expr/InfixExprTest.java | 6 +++--- .../coding/basic/stack/expr/TokenParser.java | 10 ++++++---- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 7b5892711b..030b0e3fad 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -23,7 +23,7 @@ public float evaluate() { ints.push(i1); signs.push(sign1); - while (tp.hasNextSign()) { + while (tp.hasNextInt()) { int i2 = tp.nextInt(); String sign2 = tp.nextSign(); @@ -31,20 +31,23 @@ public float evaluate() { if (tp.hasNextInt()) { - if (highPrioritySign(sign1) || lowPrioritySign(sign2) ) { - + if (highPrioritySign(sign1) || lowPrioritySign(sign2)) { i1 = ints.pop(); sign1 = signs.pop(); int result = calculate(i1, i2, sign1); ints.push(result); } else { - + ints.push(i2); } - signs.push(sign2); + if (tp.hasNextInt()) { + + signs.push(sign2); + } + sign1 = sign2; } diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index dbb3c34f21..883af2fe8c 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -17,14 +17,14 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { - // InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); } { - InfixExpr expr = new InfixExpr("3*20+12*5-40/2/2+5*2*2/2+1-10/2"); - Assert.assertEquals(116.0, expr.evaluate(), 0.001f); + InfixExpr expr = new InfixExpr("3*20+12*5-40/2/2+5*2*2/2+1-10/2*4+1"); + Assert.assertEquals(102.0, expr.evaluate(), 0.001f); } { diff --git a/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java index 785be33b88..f5f37a9a5b 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParser.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -26,13 +26,15 @@ public void parse(String expr) { String[] tokens = expr.split(""); String number = ""; + String sign = ""; for (int i = 0; i < tokens.length; i++) { String c = tokens[i]; if (isSign(c)) { - signQ.add(c); + sign = c; + signQ.add(sign); if (!number.equals("")) { int num = Integer.parseInt(number); intQ.add(num); @@ -53,9 +55,9 @@ public void parse(String expr) { if (intSize < 2 || intSize - signQ.size() > 1) { throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); } - - intQ.add(0); - signQ.add("+"); + + intQ.add(1); + signQ.add("*"); } From 30735226ce2061aebe191e1b45be2d4bd720d3df Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Sat, 15 Apr 2017 12:10:31 +0800 Subject: [PATCH 034/151] =?UTF-8?q?jvm=E7=AC=AC=E4=B8=89=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coderising/jvm/field/Field.java | 5 +- .../jvm/loader/ByteCodeIterator.java | 4 +- .../jvm/loader/ClassFileParser.java | 59 +++++++++++++++---- .../jvm/test/ClassFileloaderTest.java | 2 + 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java index 17e3b77754..98fcbf5469 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java @@ -20,12 +20,9 @@ public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool po this.pool = pool; } - - - public static Field parse(ConstantPool pool,ByteCodeIterator iter){ return null; } - + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java index 3a3e4dd7b9..8e85a3d0ab 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java @@ -58,7 +58,9 @@ public String nextUxToHexString(int len) { return Util.byteToHexString(tmp).toLowerCase(); } - + public int getPos(){ + return pos; + } public void back(int n) { this.pos -= n; } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java index 8a42fe4cb4..6bd590d869 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java @@ -1,6 +1,8 @@ package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; @@ -15,6 +17,8 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFileParser { @@ -26,7 +30,6 @@ public ClassFile parse(byte[] codes) { if(!magicNum.equals("cafebabe")){ throw new RuntimeException("文件类型错误"); } - ByteCodeIterator iter = new ByteCodeIterator(codes); int minVersion = by.nextU2Int(); int majorVersion = by.nextU2Int(); @@ -34,21 +37,25 @@ public ClassFile parse(byte[] codes) { ConstantPool constant = parseConstantPool(by); AccessFlag flag = parseAccessFlag(by); ClassIndex index = parseClassIndex(by); - - parseInterfaces(iter); + parseInterfaces(by); + List fields = parseField(by,constant); + List methods = parseMethod(by,file); file.setMinorVersion(minVersion); file.setMajorVersion(majorVersion); file.setAccessFlag(flag); file.setClassIndex(index); file.setConstPool(constant); - - + for(Field field:fields){ + file.addField(field); + } + for(Method method:methods){ + file.addMethod(method); + } + return file; } - - private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag flag = new AccessFlag(iter.nextU2Int()); return flag; @@ -115,10 +122,42 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2Int(); - - + System.out.println("interfaceCount:" + interfaceCount); } + private List parseField(ByteCodeIterator by,ConstantPool pool) { + // TODO Auto-generated method stub + List result = new ArrayList(); + int fieldCount = by.nextU2Int(); + for(int i=0;i parseMethod(ByteCodeIterator by,ClassFile file) { + // TODO Auto-generated method stub + List result = new ArrayList(); + int methodCount = by.nextU2Int(); + for(int i=0;i fields = clzFile.getFields(); Assert.assertEquals(2, fields.size()); + System.out.println("field_size:"+fields.size()); { Field f = fields.get(0); Assert.assertEquals("name:Ljava/lang/String;", f.toString()); @@ -219,6 +220,7 @@ public void testMethods(){ List methods = clzFile.getMethods(); ConstantPool pool = clzFile.getConstantPool(); + System.out.println("methods_size:"+methods.size()); { Method m = methods.get(0); From f4a4056589e258da10d0013e5815d6922f9cbd0f Mon Sep 17 00:00:00 2001 From: gongxun Date: Sat, 15 Apr 2017 17:01:24 +0800 Subject: [PATCH 035/151] =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.9/expr/ExprParser.java | 37 +++++++++++ group17/785396327/4.9/expr/InfixExpr.java | 61 ++++++++++++++++++- group17/785396327/4.9/expr/InfixExprTest.java | 9 +++ group17/785396327/4.9/expr/OperEnum.java | 21 +++++++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 group17/785396327/4.9/expr/ExprParser.java create mode 100644 group17/785396327/4.9/expr/OperEnum.java diff --git a/group17/785396327/4.9/expr/ExprParser.java b/group17/785396327/4.9/expr/ExprParser.java new file mode 100644 index 0000000000..a197377b4a --- /dev/null +++ b/group17/785396327/4.9/expr/ExprParser.java @@ -0,0 +1,37 @@ +package expr; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by IBM on 2017/4/15. + */ +public class ExprParser { + + public static List parse(InfixExpr infixExpr) { + if (infixExpr == null || infixExpr.expr == null || infixExpr.expr.trim().isEmpty()) + return null; + String[] split = infixExpr.expr.split(""); + List results = new ArrayList(); + StringBuilder numberBuffer = new StringBuilder(); + for (int i = 0; i < split.length; i++) { + String ele = split[i]; + if (ele.equals(OperEnum.ADD.getOperator()) || ele.equals(OperEnum.SUBSTRACT.getOperator()) || ele.equals(OperEnum.MINUS.getOperator()) || ele.equals(OperEnum.MULTIPLY.getOperator())) { + results.add(numberBuffer.toString()); + numberBuffer.delete(0, numberBuffer.length()); + results.add(ele); + } else + numberBuffer.append(ele); + } + results.add(numberBuffer.toString()); + return results; + } + + public static boolean belongsHighPriority(String operEle) { + return belongsOperator(operEle) && (operEle.trim().equals(OperEnum.MINUS.getOperator()) || operEle.trim().equals(OperEnum.MULTIPLY.getOperator())); + } + + public static boolean belongsOperator(String operEle) { + return (operEle != null) && (operEle.trim().equals(OperEnum.ADD.getOperator()) || operEle.trim().equals(OperEnum.SUBSTRACT.getOperator()) || operEle.trim().equals(OperEnum.MULTIPLY.getOperator()) || operEle.trim().equals(OperEnum.MINUS.getOperator())); + } +} diff --git a/group17/785396327/4.9/expr/InfixExpr.java b/group17/785396327/4.9/expr/InfixExpr.java index 035542712b..9845d45809 100644 --- a/group17/785396327/4.9/expr/InfixExpr.java +++ b/group17/785396327/4.9/expr/InfixExpr.java @@ -1,7 +1,11 @@ package expr; +import stack.MyStack; + +import java.util.List; + /** - * Created by IBM on 2017/4/13. + * Created by william on 2017/4/13. */ public class InfixExpr { String expr = null; @@ -11,8 +15,61 @@ public InfixExpr(String expr) { } public float evaluate() { + List operList = ExprParser.parse(this); + MyStack numberStack = new MyStack(); + MyStack operatorStack = new MyStack(); + if (operList != null) { + for (String operEle : operList) { + if (ExprParser.belongsOperator(operEle)) + operatorStack.push(operEle); + else { + numberStack.push(operEle); + if (!operatorStack.isEmpty() && ExprParser.belongsHighPriority(operatorStack.peek())) { + String highPriorityValue = calcHighOper(numberStack, operatorStack); + numberStack.push(highPriorityValue); + } + } + } + } + if (numberStack.size() != operatorStack.size() + 1) + throw new RuntimeException(" wrong operation number "); + return Float.parseFloat(calcSameOper(numberStack, operatorStack)); + } + + private String calcHighOper(MyStack numberStack, MyStack operatorStack) { + Float rightNumber = Float.parseFloat((String) numberStack.pop()); + Float leftNumber = Float.parseFloat((String) numberStack.pop()); + String oper = operatorStack.pop(); + return calc(rightNumber, leftNumber, oper); + } + + private String calcSameOper(MyStack numberStack, MyStack operatorStack) { + MyStack allStack = new MyStack(); + while (!operatorStack.isEmpty()) { + allStack.push(numberStack.pop()); + allStack.push(operatorStack.pop()); + } + allStack.push(numberStack.pop()); + while (allStack.size() != 1) { + Float leftNumber = Float.parseFloat((String) allStack.pop()); + String oper = (String) allStack.pop(); + Float rightNumber = Float.parseFloat((String) allStack.pop()); + allStack.push(calc(rightNumber, leftNumber, oper)); + } + return (String) allStack.pop(); + } - return 0.0f; + private String calc(Float rightNumber, Float leftNumber, String oper) { + if (oper.equals(OperEnum.ADD.getOperator())) + return leftNumber + rightNumber + ""; + else if (oper.equals(OperEnum.SUBTRACT.getOperator())) + return leftNumber - rightNumber + ""; + else if (oper.equals(OperEnum.MULTIPLY.getOperator())) + return leftNumber * rightNumber + ""; + else if (oper.equals(OperEnum.MINUS.getOperator())) + return leftNumber / rightNumber + ""; + else + throw new RuntimeException("not support " + leftNumber + " " + oper + " " + rightNumber + " operation"); } } diff --git a/group17/785396327/4.9/expr/InfixExprTest.java b/group17/785396327/4.9/expr/InfixExprTest.java index 91c19fe23e..1249bbf04b 100644 --- a/group17/785396327/4.9/expr/InfixExprTest.java +++ b/group17/785396327/4.9/expr/InfixExprTest.java @@ -5,6 +5,8 @@ import org.junit.Before; import org.junit.Test; +import java.util.List; + /** * Created by IBM on 2017/4/13. */ @@ -45,4 +47,11 @@ public void testEvaluate() { } } + + @Test + public void testExprParser() { + InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + List parse = ExprParser.parse(expr); + System.out.println(parse); + } } diff --git a/group17/785396327/4.9/expr/OperEnum.java b/group17/785396327/4.9/expr/OperEnum.java new file mode 100644 index 0000000000..adb41b75ff --- /dev/null +++ b/group17/785396327/4.9/expr/OperEnum.java @@ -0,0 +1,21 @@ +package expr; + +/** + * Created by IBM on 2017/4/15. + */ +public enum OperEnum { + ADD("+"), SUBTRACT("-"), MULTIPLY("*"), MINUS("/"); + private String operator; + + OperEnum(String operator) { + this.operator = operator; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } +} From 565d9ef8434b517b12076b7f8080cc10f55a3aea Mon Sep 17 00:00:00 2001 From: GordenChow <513274874@qq.com> Date: Sat, 15 Apr 2017 17:45:12 +0800 Subject: [PATCH 036/151] =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 第六周作业备份,数据结构一完成test,jvm尚未test --- .../src/com/coding/basic/stack/StackUtil.java | 26 +++-- .../com/coding/basic/stack/StackUtilTest.java | 76 ++++++++++++++ .../coding/basic/stack/expr/InfixExpr.java | 98 +++++++++++++++++++ .../basic/stack/expr/InfixExprTest.java | 48 +++++++++ .../coderising/jvm/attr/AttributeInfo.java | 19 ++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 94 ++++++++++++++++++ .../coderising/jvm/attr/LineNumberTable.java | 55 +++++++++++ .../jvm/attr/LocalVariableItem.java | 39 ++++++++ .../jvm/attr/LocalVariableTable.java | 42 ++++++++ .../coderising/jvm/attr/StackMapTable.java | 30 ++++++ .../src/com/coderising/jvm/clz/ClassFile.java | 21 +++- .../coderising/jvm/constant/ConstantInfo.java | 5 - .../coderising/jvm/constant/ConstantPool.java | 4 +- .../jvm/constant/MethodRefInfo.java | 3 +- .../src/com/coderising/jvm/field/Field.java | 44 +++++++++ .../jvm/loader/ByteCodeIterator.java | 44 ++++++--- .../jvm/loader/ClassFileParser.java | 32 ++++++ .../src/com/coderising/jvm/method/Method.java | 76 ++++++++++++++ .../jvm/test/ClassFileloaderTest.java | 81 +++++++++++++-- 19 files changed, 802 insertions(+), 35 deletions(-) create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/StackUtilTest.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java index e53e38ca4b..fa8a8c0325 100755 --- a/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java @@ -1,5 +1,6 @@ package com.coding.basic.stack; +import java.util.Stack; public class StackUtil { /** @@ -7,14 +8,27 @@ public class StackUtil { * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ public static void reverse(Stack s) { - Stack temp = new Stack(); - //先清空s - while (!s.isEmpty()) { - temp.push(s.pop()); + if(null == s || s.isEmpty()){ + return; } + Object object = s.pop(); + reverse(s); + addToBottom(s,object); } + public static void addToBottom(Stack s ,Object num){ + if(s.isEmpty()){ + s.push(num); + + }else{ + Object o = s.pop(); + addToBottom(s,num); + s.push(o); + } + } + + /** * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 * @@ -101,7 +115,7 @@ public static boolean isValidPairs(String s) { break; case ']': temp = (byte) stack.peek(); - if (temp != ']') { + if (temp != '[') { return false; } else { stack.pop(); @@ -109,7 +123,7 @@ public static boolean isValidPairs(String s) { break; case '}': temp = (byte) stack.peek(); - if (temp != ']') { + if (temp != '{') { return false; } else { stack.pop(); diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtilTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..d183607f63 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,76 @@ +package com.coding.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Stack; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddToBottom() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..ddd255e4a0 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,98 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.StackUtil; + +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + char[] chars = expr.toCharArray(); + System.out.println(chars); + + Stack numStack = new Stack(); + Stack operStack = new Stack(); + //当前数,有可能是操作数,有可能是运算符 + String curr = ""; + OperIterator operIterator = new OperIterator(chars); + int num = operIterator.nextNumber(); + numStack.push(num); + while(operIterator.hasNext()){ + int numB = 0; + char oper = operIterator.nextOperator(); + switch (oper){ + case '+': + case '-': + operStack.push(oper); + numStack.push(operIterator.nextNumber()); + continue; + case '*': + numB = operIterator.nextNumber(); + numStack.push(Double.parseDouble(numStack.pop() + "") * numB); + continue; + case '/': + numB = operIterator.nextNumber(); + numStack.push(Double.parseDouble(numStack.pop()+"") / numB); + continue; + } + } + + //清算站内数据 + if(operStack.isEmpty()) return Float.parseFloat(numStack.pop() + ""); + + StackUtil.reverse(operStack); + StackUtil.reverse(numStack); + while(!operStack.isEmpty()){ + char oper = (char)operStack.pop(); + + numStack.push(operate(Float.parseFloat(numStack.pop()+""),Float.parseFloat(numStack.pop() +""),oper)); + } + + return (float) numStack.pop(); + } + + private float operate(float a,float b,char oper){ + switch (oper){ + case '-': + return a-b; + case '+': + return a+b; + case '*': + return a*b; + case '/': + return a/b; + } + return 0.00f; + } + + class OperIterator { + private char[] expr ; + private int pos = 0; + + public OperIterator(char[] expr) { + this.expr = expr; + } + + public char nextOperator(){ + return expr[pos++]; + } + public int nextNumber(){ + StringBuffer num = new StringBuffer(""); + while(pos <= expr.length-1 && expr[pos] != '+' && expr[pos] != '-' && expr[pos] != '*' && expr[pos] != '/'){ + num.append(expr[pos++]); + } + return Integer.parseInt(num.toString()); + } + + public boolean hasNext(){ + return pos < expr.length-1; + } + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..343683f11a --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..89fb53394e --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..1194321d0d --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,94 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.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 attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Int(); + int maxStack = iter.nextU2Int(); + int maxLocals = iter.nextU2Int(); + + int codeLength = iter.nextU4Int(); + String code = iter.nextUxToHexString(codeLength); + + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + + //exception + int exceptionTableLength = iter.nextU2Int(); + if (exceptionTableLength > 0) { + String exceptionTable = iter.nextUxToHexString(exceptionTableLength); + throw new RuntimeException("there's exception to be implemented !!"); + } + + //attribute table of the code + int attributesCount = iter.nextU2Int(); + for (int i = 0; i < attributesCount; i++) { + int subAttributeNameIndex = iter.nextU2Int(); + iter.back(2); + + String subAttributeName = clzFile.getConstantPool().getUTF8String(subAttributeNameIndex); + + if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { + + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + + } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { + + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + + } else { + throw new RuntimeException("there's other sub attribute to added : name = " + subAttributeName); + } + + } + + return codeAttr; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..1e969ef3ee --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTable extends AttributeInfo { + List 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 attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Int(); + LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex,attributeLength); + + //lineNumberItem block + int lineNumberTableLength = iter.nextU2Int(); + for(int i = 0 ;i items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + int attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Int(); + + LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex,attributeLength); + + int localVariableTableLength = iter.nextU2Int(); + for(int i = 0 ;i < localVariableTableLength;i++){ + LocalVariableItem localVariableItem = new LocalVariableItem(); + localVariableItem.setStartPC(iter.nextU2Int()); + localVariableItem.setLength(iter.nextU2Int()); + localVariableItem.setDescIndex(iter.nextU2Int()); + localVariableItem.setIndex(iter.nextU2Int()); + localVariableTable.addLocalVariableItem(localVariableItem); + } + + + return localVariableTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..3a8b6b8013 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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.nextU2Int(); + int len = iter.nextU4Int(); + 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/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java index 650ca8375d..4755266987 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -1,7 +1,12 @@ package com.coderising.jvm.clz; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFile { @@ -11,7 +16,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; @@ -48,7 +54,18 @@ public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - + 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 print(){ diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java index 5d66317801..466b072244 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -18,11 +18,6 @@ public ConstantInfo(ConstantPool pool) { this.constantPool = pool; } public abstract int getType(); - - @Override - public String toString(){ - return super.toString(); - } public ConstantPool getConstantPool() { return constantPool; diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java index f92c8028b9..86c0445695 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -1,11 +1,11 @@ package com.coderising.jvm.constant; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; public class ConstantPool { - private List constantInfos = new LinkedList(); + private List constantInfos = new ArrayList(); public ConstantPool(){ diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java index 65c586916c..9568c571d8 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -27,8 +27,7 @@ public int getNameAndTypeIndex() { public void setNameAndTypeIndex(int nameAndTypeIndex) { this.nameAndTypeIndex = nameAndTypeIndex; } - - @Override + public String toString(){ return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..d3a642a109 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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; + } + + @Override + public String toString() { + return super.toString(); + } + + public static Field parse(ConstantPool pool, ByteCodeIterator iter) { + int accessFlag = iter.nextU2Int(); + int nameIndex = iter.nextU1Int(); + int descriptorIndex = iter.nextU2Int(); + + int attributsCount = iter.nextU2Int(); + + if (attributsCount > 0) { + throw new RuntimeException("field : " + ((UTF8Info) pool.getConstantInfo(nameIndex)).getValue() + "has attributes to be implemented !!"); + } + + Field field = new Field(accessFlag,nameIndex,descriptorIndex,pool); + return field; + } + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java index e4c5c83681..59d072ef0b 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -5,30 +5,50 @@ import java.util.Arrays; public class ByteCodeIterator { - private byte[] code ; + private byte[] code; private int pos = 0; public ByteCodeIterator(byte[] code) { this.code = code; } - public int nextU1Int(){ + public byte[] getBytes(int length) { + if (pos + length >= code.length) { + throw new IndexOutOfBoundsException("not enough bytes!"); + } + byte[] bytes = Arrays.copyOfRange(code, pos, pos + length); + pos += length; + return bytes; + } + + public int nextU1Int() { return Util.byteToInt(new byte[]{code[pos++]}); } - public int nextU2Int(){ - return Util.byteToInt(new byte[]{code[pos++],code[pos++]}); + public int nextU2Int() { + + return Util.byteToInt(new byte[]{code[pos++], code[pos++]}); } - public String nextU4HexString(){ - return Util.byteToHexString(new byte[]{code[pos++],code[pos++],code[pos++],code[pos++]}); + + public int nextU4Int() { + return Util.byteToInt(new byte[]{code[pos++], code[pos++], code[pos++], code[pos++]}); } - public byte[] getBytes(int length){ - if(pos+length >= code.length){ - throw new IndexOutOfBoundsException("not enough bytes!"); + public String nextU4HexString() { + return Util.byteToHexString(new byte[]{code[pos++], code[pos++], code[pos++], code[pos++]}); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = code[pos++]; } - byte[] bytes = Arrays.copyOfRange(code,pos,pos+length); - pos += length; - return bytes; + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java index 0c35bca807..e9bfa54720 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -4,6 +4,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; import com.coderising.jvm.constant.*; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; import java.io.UnsupportedEncodingException; @@ -26,6 +28,10 @@ public ClassFile parse(byte[] codes) { clzFile.setAccessFlag(parseAccessFlag(iterator)); clzFile.setClassIndex(parseClassIndex(iterator)); + parseInterfaces(iterator); + parseFields(clzFile,iterator); + parseMethods(clzFile,iterator); + return clzFile; } @@ -102,8 +108,34 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { } } + System.out.println("Finished reading Constant pool "); return pool; } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2Int(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFields(ClassFile clazzFile,ByteCodeIterator iterator){ + int fieldCount = iterator.nextU2Int(); + for (int i = 0 ;i 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 0174facd5e8f039d2b24164b7d7c0f432f03f873 Mon Sep 17 00:00:00 2001 From: GordenChow <513274874@qq.com> Date: Sat, 15 Apr 2017 22:19:49 +0800 Subject: [PATCH 037/151] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E7=AC=AC=E5=85=AD?= =?UTF-8?q?=E5=91=A8=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jvm单元测试通过 --- .../mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java | 2 +- .../src/com/coderising/jvm/attr/LocalVariableTable.java | 1 + .../mini-jvm/src/com/coderising/jvm/field/Field.java | 7 +++++-- .../mini-jvm/src/com/coderising/jvm/method/Method.java | 4 ++-- .../src/com/coderising/jvm/test/ClassFileloaderTest.java | 9 +++++---- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java index 1194321d0d..cf37bf22aa 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -71,7 +71,7 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { LineNumberTable lineNumberTable = LineNumberTable.parse(iter); codeAttr.setLineNumberTable(lineNumberTable); - } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { + } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LOCAL_VAR_TABLE)) { LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); codeAttr.setLocalVariableTable(localVariableTable); diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java index 9547f95d68..93d2af0d62 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -26,6 +26,7 @@ public static LocalVariableTable parse(ByteCodeIterator iter){ LocalVariableItem localVariableItem = new LocalVariableItem(); localVariableItem.setStartPC(iter.nextU2Int()); localVariableItem.setLength(iter.nextU2Int()); + localVariableItem.setNameIndex(iter.nextU2Int()); localVariableItem.setDescIndex(iter.nextU2Int()); localVariableItem.setIndex(iter.nextU2Int()); localVariableTable.addLocalVariableItem(localVariableItem); diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java index d3a642a109..acbb77410a 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/field/Field.java @@ -23,12 +23,15 @@ public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool po @Override public String toString() { - return super.toString(); + String name = pool.getUTF8String(nameIndex); + String descr = pool.getUTF8String(descriptorIndex); + + return name+":"+descr; } public static Field parse(ConstantPool pool, ByteCodeIterator iter) { int accessFlag = iter.nextU2Int(); - int nameIndex = iter.nextU1Int(); + int nameIndex = iter.nextU2Int(); int descriptorIndex = iter.nextU2Int(); int attributsCount = iter.nextU2Int(); diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java index fd0713d9ca..3d2c8e2554 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java @@ -66,11 +66,11 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { method.setCodeAttr(codeAttr); } else { - throw new RuntimeException("there's other method attribute to be implemented !!"); + throw new RuntimeException("there's other method attribute to be implemented:attributeName = " + attributeName); } } - return null; + return method; } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java index dcdff98cf7..bd32473909 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -19,14 +19,15 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "/Users/guodongchow/Desktop/coding2017/projects/mini-jvm/bin/"; - static String path2 = "/Users/guodongchow/bin"; +// static String path1 = "/Users/guodongchow/Desktop/coding2017/projects/mini-jvm/bin/"; + static String path1 = "/Users/guodongchow/Desktop/coding2017/"; + static String path2 = "/Users/guodongchow/bin/"; static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "EmployeeV1"; clzFile = loader.loadClass(className); clzFile.print(); @@ -60,7 +61,7 @@ public void testClassFileLength() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); From d1fabaf5a3835854e6ecd29498d313531f15185a Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 16 Apr 2017 10:14:32 +0800 Subject: [PATCH 038/151] last fix --- .../coding/basic/stack/expr/InfixExpr.java | 26 ++++++--------- .../basic/stack/expr/InfixExprTest.java | 32 +++++++++++++++++-- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 030b0e3fad..4174b0a693 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -28,26 +28,18 @@ public float evaluate() { int i2 = tp.nextInt(); String sign2 = tp.nextSign(); - if (tp.hasNextInt()) { - - if (highPrioritySign(sign1) || lowPrioritySign(sign2)) { - i1 = ints.pop(); - sign1 = signs.pop(); - int result = calculate(i1, i2, sign1); - ints.push(result); - - } else { - - ints.push(i2); - - } - if (tp.hasNextInt()) { + if (highPrioritySign(sign1)) { - signs.push(sign2); + i1 = ints.pop(); + sign1 = signs.pop(); + i2 = calculate(i1, i2, sign1); + } - + + ints.push(i2); + signs.push(sign2); sign1 = sign2; } @@ -105,7 +97,7 @@ private boolean lowPrioritySign(String sign) { return false; } - + private boolean highPrioritySign(String sign) { if (sign.equals("*") || sign.equals("/")) { diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index 883af2fe8c..666265df6c 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -17,20 +17,46 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { - //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); } + + { + InfixExpr expr = new InfixExpr("2+3*4+5*1+1"); + Assert.assertEquals(20.0, expr.evaluate(), 0.001f); + } + { - InfixExpr expr = new InfixExpr("3*20+12*5-40/2/2+5*2*2/2+1-10/2*4+1"); - Assert.assertEquals(102.0, expr.evaluate(), 0.001f); + InfixExpr expr = new InfixExpr("2+3*4/2"); + Assert.assertEquals(8.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("2-3*4/2-1"); + Assert.assertEquals(-5.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("6-1*5+2+0"); + Assert.assertEquals(3.0, expr.evaluate(), 0.001f); } { InfixExpr expr = new InfixExpr("3*20/2"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } + + { + InfixExpr expr = new InfixExpr("3*20/2+1"); + Assert.assertEquals(31, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2+1-1"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } { InfixExpr expr = new InfixExpr("20/2*3"); From 6d4a5998cf81d4dd46b142a7d66e625c1ab3f07f Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 16 Apr 2017 10:27:11 +0800 Subject: [PATCH 039/151] we can do better --- .../382266293/coding/basic/stack/expr/InfixExpr.java | 12 +----------- .../coding/basic/stack/expr/InfixExprTest.java | 5 +++++ .../coding/basic/stack/expr/TokenParser.java | 3 +-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 4174b0a693..2b4d531c40 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -46,6 +46,7 @@ public float evaluate() { } + signs.pop(); StackUtil.reverse(ints); StackUtil.reverse(signs); @@ -86,17 +87,6 @@ private int calculate(int firstInt, int secInt, String lowsign) { return result; } - - private boolean lowPrioritySign(String sign) { - - if (sign.equals("+") || sign.equals("-")) { - - return true; - - } - - return false; - } private boolean highPrioritySign(String sign) { diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index 666265df6c..791ea67e43 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -18,6 +18,11 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { + { + InfixExpr expr = new InfixExpr("1*2*2-1"); + Assert.assertEquals(3.0, expr.evaluate(), 0.001f); + } + { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); diff --git a/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java index f5f37a9a5b..4fa0d7b79e 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParser.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -56,8 +56,7 @@ public void parse(String expr) { throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); } - intQ.add(1); - signQ.add("*"); + intQ.add(0); } From 14a24decf77222f3f987c521cc5ae20f465bf245 Mon Sep 17 00:00:00 2001 From: GUK0 <1685605435@qq.com> Date: Sun, 16 Apr 2017 13:34:10 +0800 Subject: [PATCH 040/151] =?UTF-8?q?=E7=AC=AC7=E5=91=A8=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=EF=BC=8CJunit=E6=B5=8B=E8=AF=95=E6=9C=89?= =?UTF-8?q?=E7=82=B9=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../structure/week2/ArrayUtilTest.java | 1 - .../247565311/structure/week6/StackUtil.java | 40 +++---- .../structure/week6/StackUtilTest.java | 7 +- .../247565311/structure/week7/InfixExpr.java | 93 ++++++++++++--- .../structure/week7/InfixExprTest.java | 112 ++++++++++-------- .../week567_miniJVM/attr/AttrFactory.java | 80 +++++++++++++ .../week567_miniJVM/attr/AttributeInfo.java | 19 +-- .../week567_miniJVM/attr/CodeAttr.java | 53 ++++----- .../week567_miniJVM/attr/LineNumberTable.java | 18 ++- .../attr/LocalVariableItem.java | 7 ++ .../attr/LocalVariableTable.java | 6 +- .../week567_miniJVM/attr/StackMapTable.java | 2 +- .../week567_miniJVM/clz/ClassFile.java | 76 ++++++------ .../constant/ConstantPool.java | 6 - .../week567_miniJVM/constant/InfoFactory.java | 54 +++++++++ .../week567_miniJVM/constant/UTF8Info.java | 3 - .../week567_miniJVM/field/Field.java | 33 ++---- .../loader/ByteCodeIterator.java | 34 ++++-- .../loader/ClassFileLoader.java | 24 ++-- .../{test => loader}/ClassFileLoaderTest.java | 44 +++---- .../loader/ClassFileParser.java | 105 +++++++++++----- .../week567_miniJVM/method/Method.java | 47 ++++---- .../week567_miniJVM/test/EmployeeV1.java | 15 ++- .../247565311/week567_miniJVM/util/Util.java | 3 - 24 files changed, 557 insertions(+), 325 deletions(-) create mode 100644 group12/247565311/week567_miniJVM/attr/AttrFactory.java create mode 100644 group12/247565311/week567_miniJVM/constant/InfoFactory.java rename group12/247565311/week567_miniJVM/{test => loader}/ClassFileLoaderTest.java (93%) diff --git a/group12/247565311/structure/week2/ArrayUtilTest.java b/group12/247565311/structure/week2/ArrayUtilTest.java index c1b414d725..3d249b7225 100644 --- a/group12/247565311/structure/week2/ArrayUtilTest.java +++ b/group12/247565311/structure/week2/ArrayUtilTest.java @@ -8,7 +8,6 @@ public class ArrayUtilTest { ArrayUtil u = null; @Before public void setUp() throws Exception { - System.out.println("��ʼһ���µIJ���"); u = new ArrayUtil(); } diff --git a/group12/247565311/structure/week6/StackUtil.java b/group12/247565311/structure/week6/StackUtil.java index 9895f02f30..4529372e4c 100644 --- a/group12/247565311/structure/week6/StackUtil.java +++ b/group12/247565311/structure/week6/StackUtil.java @@ -2,20 +2,10 @@ import java.util.Stack; public class StackUtil { - public static void bad_reverse(Stack s) { - if(s == null || s.isEmpty()){ - return; - } - Stack tmpStack = new Stack(); - while(!s.isEmpty()){ - tmpStack.push(s.pop()); - } - s = tmpStack; - } - + /** - * 閸嬪洩顔曢弽鍫滆厬閻ㄥ嫬鍘撶槐鐘虫ЦInteger, 娴犲孩鐖ゆい璺哄煂閺嶅牆绨抽弰锟� 5,4,3,2,1 鐠嬪啰鏁ょ拠銉︽煙濞夋洖鎮楅敍锟介崗鍐濞嗏�绨崣妯硅礋: 1,2,3,4,5 - * 濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,pop,peek,isEmpty閿涳拷閸欘垯浜掓担璺ㄦ暏閸欙箑顦绘稉锟介嚋閺嶅牊娼垫潏鍛И + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ public static void reverse(Stack s){ if(s == null || s.isEmpty()) return; @@ -27,22 +17,26 @@ public static void reverse(Stack s){ } while(!s1.isEmpty()) s.push(s1.pop()); + for(int i=0;ii) + int index = 1; + while(index+i0) + while(!s1.isEmpty()) s.push(s1.pop()); } } - // 閫氳繃閫掑綊鍙互涓嶄娇鐢ㄥ爢鏍堝畬鎴愯繖涓�姛鑳� + // 原地翻转栈也可以使用递归的方式,就是不好理解 public static void reverse2(Stack s) { if(s == null || s.isEmpty()){ return; } Integer top = s.pop(); - reverse(s); + reverse2(s); addToBottom(s,top); } public static void addToBottom(Stack s, Integer value){ @@ -55,7 +49,7 @@ public static void addToBottom(Stack s, Integer value){ } } /** - * 閸掔娀娅庨弽鍫滆厬閻ㄥ嫭鐓囨稉顏勫帗缁憋拷濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,pop,peek,isEmpty閿涳拷閸欘垯浜掓担璺ㄦ暏閸欙箑顦绘稉锟介嚋閺嶅牊娼垫潏鍛И + * 移出栈中的某个元素,只能使用push,pop,peek,isEmpty这几种操作 * * @param o */ @@ -76,7 +70,7 @@ public static void remove(Stack s,Object o) { } /** - * 娴犲孩鐖ゆい璺哄絿瀵版en娑擃亜鍘撶槐锟�閸樼喐娼甸惃鍕垽娑擃厼鍘撶槐鐘辩箽閹镐椒绗夐崣锟� * 濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,pop,peek,isEmpty閿涳拷閸欘垯浜掓担璺ㄦ暏閸欙箑顦绘稉锟介嚋閺嶅牊娼垫潏鍛И + * 获取栈顶的len个元素,只能使用push,pop,peek,isEmpty这几种操作来完成 * @param len * @return */ @@ -98,10 +92,10 @@ public static Object[] getTop(Stack s,int len) { return result; } /** - * 鐎涙顑佹稉鐬�閸欘垵鍏橀崠鍛儓鏉╂瑤绨虹�妤冾儊閿涳拷 ( ) [ ] { }, a,b,c... x,yz - * 娴h法鏁ら崼鍡樼垽濡拷鐓$�妤冾儊娑撶灚娑擃厾娈戦幏顒�娇閺勵垯绗夐弰顖涘灇鐎电懓鍤悳鎵畱閵嗭拷 - * 娓氬顩 = "([e{d}f])" , 閸掓瑨顕氱�妤冾儊娑撹弓鑵戦惃鍕閸欓攱妲搁幋鎰嚠閸戣櫣骞囬敍锟界拠銉︽煙濞夋洝绻戦崶鐎焤ue - * 婵″倹鐏�s = "([b{x]y})", 閸掓瑨顕氱�妤冾儊娑撹弓鑵戦惃鍕閸欒渹绗夐弰顖涘灇鐎电懓鍤悳鎵畱閿涳拷鐠囥儲鏌熷▔鏇$箲閸ョ�alse; + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; * @param s * @return */ diff --git a/group12/247565311/structure/week6/StackUtilTest.java b/group12/247565311/structure/week6/StackUtilTest.java index f1a8aec8ac..74c10b3ffd 100644 --- a/group12/247565311/structure/week6/StackUtilTest.java +++ b/group12/247565311/structure/week6/StackUtilTest.java @@ -1,13 +1,12 @@ package structure.week6; -import static org.junit.Assert.fail; - import java.util.Stack; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; + public class StackUtilTest { @Before @@ -24,11 +23,8 @@ public void testAddToBottom() { s.push(1); s.push(2); s.push(3); - StackUtil.addToBottom(s, 0); - Assert.assertEquals("[0, 1, 2, 3]", s.toString()); - } @Test public void testReverse() { @@ -74,5 +70,4 @@ public void testIsValidPairs() { Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); } - } \ No newline at end of file diff --git a/group12/247565311/structure/week7/InfixExpr.java b/group12/247565311/structure/week7/InfixExpr.java index 4fc4d13fbe..1cb09a5d0b 100644 --- a/group12/247565311/structure/week7/InfixExpr.java +++ b/group12/247565311/structure/week7/InfixExpr.java @@ -1,17 +1,20 @@ package structure.week7; -// 姹傝В琛ㄨ揪寮忓瓧绗︿覆锛岄鍏堝皢琛ㄨ揪寮忓垱寤烘垚涓�5琛ㄨ揪寮忔爲锛岄渶瑕佹牴鎹繍绠楃鐨勪紭鍏堢骇鏉ュ垱寤� +import structure.week1.Stack; +// 使用表达式树来完成这个运算 public class InfixExpr { String expr = null; Element getElem = null; public InfixExpr(String expr) { - this.expr = expr; + this.expr = "0+"+expr; // 由于遇到优先级变化会生成单独节点,必须以最低优先级开头 getElem = new Element(expr); } public float evaluate() throws Exception{ - Node node = new Node('\0',getElem.getNextNum()); - Node root = createNode(node); + Node root = createNode(null); return (float) getValue(root); } + public double evaluate_stack(){ + return 0.0; + } class Element{ private int index; private String str; @@ -19,7 +22,35 @@ public Element(String _str){ index = 0; str = _str; } - public double getNextNum(){ + public double peekNextNum(){ + int lastindex = index; + double resl = 0,resr=0; + int fbits = 0; + char ch = str.charAt(index); + boolean hasp = false; + while(ch=='.' || (ch<='9' && '0'<=ch)){ + index += 1; + if(ch == '.') hasp = true; + else{ + if(hasp){ + fbits -= 1; + resr += (double)(ch-'0') * Math.pow(10,fbits); + }else{ + resl *= 10; + resl += (ch-'0'); + } + } + if(hasNext()) ch = str.charAt(index); + else break; + } + index = lastindex; + return resl+resr; + } + public double getNextNum() throws Exception{ + if(!hasNext()) { + int a = index -2; + throw new Exception("表达式格式错误,在位置"+a+"处缺少操作数。"); + } double resl = 0,resr=0; int fbits = 0; char ch = str.charAt(index); @@ -41,6 +72,18 @@ public double getNextNum(){ } return resl+resr; } + public char peekNextOper(){ + int lastindex = index; + char ch = '\0'; + while(hasNext()){ + ch = str.charAt(index); + index += 1; + if(ch=='+'||ch=='-'||ch=='*'||ch=='/') break; + ch = '\0'; + } + index = lastindex; + return ch; + } public char getNextOper(){ if(hasNext()){ char ch = str.charAt(index); @@ -68,23 +111,37 @@ class Node{ val =v; } } - private Node createNode(Node root){ + private Node createNode(Node node) throws Exception{ + if(getElem.peekNextOper() == '\0') return node; + if(node == null){ + node = new Node('\0',getElem.getNextNum()); + } char ch = getElem.getNextOper(); - if(ch == '\0'){ - + Node root = new Node(ch,0); + root.left = node; + char chn = getElem.peekNextOper(); + if(operUpDowm(ch,chn)<0){ // 操作符优先级提升 + root.right = createNode(null); + }else if(operUpDowm(ch,chn)>0){ // 操作符优先级下降 + root.right = new Node('\0',getElem.getNextNum()); + return root; // 这里是遍历完一个连续乘除法,需要返回节点,考虑5-2*3-4,不返回会导致5-2*3+4 }else{ - + root.right = new Node('\0',getElem.getNextNum()); } - Node node = new Node(getElem.getNextOper(),0); - node.left = root; - node.right = null; - // todo - return node; + return createNode(root); + } + private int operUpDowm(char c1,char c2){ + int temp1 = 0,temp2=0; + if(c1=='+'||c1=='-')temp1 = 0; + else if(c1=='*'||c1=='/')temp1 = 1; + if(c2=='+'||c2=='-')temp2 = 0; + else if(c2=='*'||c2=='/')temp2 = 1; + return temp1-temp2; } private double getValue(Node root) throws Exception{ - if(root == null) throw new Exception("表达式非法"); + if(root == null) throw new Exception("解析表达式出现异常"); switch(root.op){ - case '+': + case '+': return getValue(root.left)+getValue(root.right); case '-': return getValue(root.left)-getValue(root.right); @@ -92,8 +149,10 @@ private double getValue(Node root) throws Exception{ return getValue(root.left)*getValue(root.right); case '/': return getValue(root.left)/getValue(root.right); - default: + case '\0': return root.val; + default: + throw new Exception("目前还不支持 "+new StringBuilder().append(root.op).toString()+" 运算符。"); } } } diff --git a/group12/247565311/structure/week7/InfixExprTest.java b/group12/247565311/structure/week7/InfixExprTest.java index 21680594de..730e623126 100644 --- a/group12/247565311/structure/week7/InfixExprTest.java +++ b/group12/247565311/structure/week7/InfixExprTest.java @@ -6,58 +6,66 @@ public class InfixExprTest { - @Before - public void setUp() throws Exception { - } - @After - public void tearDown() throws Exception { - } - @Test - public void testEvaluate() { - //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); - { - InfixExpr expr = new InfixExpr("2+3*4+5"); - try { - Assert.assertEquals(19.0, expr.evaluate(), 0.001f); - } catch (Exception e) { - e.printStackTrace(); - } - } + @Before + public void setUp() throws Exception { + } + @After + public void tearDown() throws Exception { + } + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + try { + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } - { - InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); - try { - Assert.assertEquals(100.0, expr.evaluate(), 0.001f); - } catch (Exception e) { - e.printStackTrace(); - } - } - - { - InfixExpr expr = new InfixExpr("3*20/2"); - try { - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } catch (Exception e) { - e.printStackTrace(); - } - } - - { - InfixExpr expr = new InfixExpr("20/2*3"); - try { - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } catch (Exception e) { - e.printStackTrace(); - } - } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + try { + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } - { - InfixExpr expr = new InfixExpr("10-30+50"); - try { - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } catch (Exception e) { - e.printStackTrace(); - } - } - } + { + InfixExpr expr = new InfixExpr("3*20/2"); + try { + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + try { + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + try { + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } + { + InfixExpr expr = new InfixExpr("4*2*5+5-4*5/5*3/2*4-2+4*2+2/1"); + try { + Assert.assertEquals(29, expr.evaluate(), 0.001f); + } catch (Exception e) { + e.printStackTrace(); + } + } + } } \ No newline at end of file diff --git a/group12/247565311/week567_miniJVM/attr/AttrFactory.java b/group12/247565311/week567_miniJVM/attr/AttrFactory.java new file mode 100644 index 0000000000..71992f4302 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/AttrFactory.java @@ -0,0 +1,80 @@ +package week567_miniJVM.attr; + +import week567_miniJVM.clz.ClassFile; +import week567_miniJVM.constant.ConstantInfo; +import week567_miniJVM.constant.UTF8Info; +import week567_miniJVM.loader.ByteCodeIterator; +import week567_miniJVM.attr.LineNumberTable; + +public class AttrFactory{ + private static AttrFactory instance = new AttrFactory(); + public static AttrFactory Instance(){ + return instance; + } + public AttributeInfo parse(ClassFile clzFile,ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2ToInt(); + ConstantInfo info = clzFile.getConstantPool().getConstantInfo(attrNameIndex); + if(info.getType()==1&&"Code".equals(((UTF8Info) info).getValue())){ + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocal = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + String code = iter.nextUxToHexString(codeLen); + CodeAttr codeattr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocal,codeLen,code); + + int exceptLen = iter.nextU2ToInt(); // �쳣���� + while(exceptLen>0){ + exceptLen -= 1; + int startPc = iter.nextU2ToInt(); + int endPc = iter.nextU2ToInt(); + int handlerPc = iter.nextU2ToInt(); + int catchType = iter.nextU2ToInt(); + // TODO + } + int attributeLen = iter.nextU2ToInt(); // �����»������Եĸ��� + while(attributeLen>0){ + attributeLen -= 1; + AttributeInfo chattr = AttrFactory.Instance().parse(clzFile, iter); + codeattr.addAttr(chattr); + } + return codeattr; + }else if(info.getType()==1&&"LineNumberTable".equals(((UTF8Info) info).getValue())){ + int attrLen = iter.nextU4ToInt(); + int lineNum = iter.nextU2ToInt(); + LineNumberTable linetable = new LineNumberTable(attrNameIndex,lineNum); + while(lineNum>0){ + lineNum -= 1; + int startPc = iter.nextU2ToInt(); + int lineNumber = iter.nextU2ToInt(); + linetable.addLineNumberItem(startPc,lineNumber); + } + return linetable; + }else if(info.getType()==1&&"LocalVariableTable".equals(((UTF8Info) info).getValue())){ + int attrLen = iter.nextU4ToInt(); + int localVarNum = iter.nextU2ToInt(); + LocalVariableTable lvartable = new LocalVariableTable(attrNameIndex,localVarNum); + while(localVarNum>0){ + localVarNum -= 1; + int startPc = iter.nextU2ToInt(); + int length = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int index = iter.nextU2ToInt(); + LocalVariableItem item = new LocalVariableItem(startPc,length,nameIndex,descIndex,index); + lvartable.addLocalVariableItem(item); + } + return lvartable; + }else if(info.getType()==1&&"StackMapTable".equals(((UTF8Info) info).getValue())){ + int attrLen = iter.nextU4ToInt(); + int entryNum = iter.nextU2ToInt(); + StackMapTable stacktable = new StackMapTable(attrNameIndex,entryNum); + stacktable.parse(iter); + //while(entryNum>0){ + // entryNum -= 1; + + //} + return stacktable; + } + return null; + } +} \ No newline at end of file diff --git a/group12/247565311/week567_miniJVM/attr/AttributeInfo.java b/group12/247565311/week567_miniJVM/attr/AttributeInfo.java index e97ebe0065..fb310678bf 100644 --- a/group12/247565311/week567_miniJVM/attr/AttributeInfo.java +++ b/group12/247565311/week567_miniJVM/attr/AttributeInfo.java @@ -1,7 +1,6 @@ package week567_miniJVM.attr; - - +import structure.week1.ArrayList; public abstract class AttributeInfo { public static final String CODE = "Code"; @@ -12,13 +11,19 @@ public abstract class AttributeInfo { public static final String STACK_MAP_TABLE = "StackMapTable"; int attrNameIndex; int attrLen ; - public AttributeInfo(int attrNameIndex, int attrLen) { - - this.attrNameIndex = attrNameIndex; + private String attrName; + ArrayList attrs = new ArrayList(); + public AttributeInfo( int attrNameIndex,int attrLen,String attrname) { + this.attrNameIndex = attrNameIndex; this.attrLen = attrLen; + this.attrName = attrname; + } + public String getAttrName(){ + return attrName; + } + public void addAttr(AttributeInfo attrinfo){ + attrs.add(attrinfo); } - - } diff --git a/group12/247565311/week567_miniJVM/attr/CodeAttr.java b/group12/247565311/week567_miniJVM/attr/CodeAttr.java index b32d6aada9..15e0a027f2 100644 --- a/group12/247565311/week567_miniJVM/attr/CodeAttr.java +++ b/group12/247565311/week567_miniJVM/attr/CodeAttr.java @@ -1,13 +1,10 @@ - - package week567_miniJVM.attr; import week567_miniJVM.clz.ClassFile; import week567_miniJVM.constant.ConstantPool; import week567_miniJVM.loader.ByteCodeIterator; - public class CodeAttr extends AttributeInfo { private int maxStack ; private int maxLocals ; @@ -16,46 +13,40 @@ public class CodeAttr extends AttributeInfo { 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); + super(attrNameIndex, attrLen,AttributeInfo.CODE); this.maxStack = maxStack; this.maxLocals = maxLocals; this.codeLen = codeLen; this.code = code; - //this.cmds = cmds; } - public void setLineNumberTable(LineNumberTable t) { - this.lineNumTable = t; + public LineNumberTable getLineNumberTable() { + for(int i=0;i items = new ArrayList(); public LocalVariableTable(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); + super(attrNameIndex, attrLen,AttributeInfo.LOCAL_VAR_TABLE); } - public static LocalVariableTable parse(ByteCodeIterator iter){ return null; } - private void addLocalVariableItem(LocalVariableItem item) { + public void addLocalVariableItem(LocalVariableItem item) { this.items.add(item); } + } diff --git a/group12/247565311/week567_miniJVM/attr/StackMapTable.java b/group12/247565311/week567_miniJVM/attr/StackMapTable.java index c6b72f2655..aaf8d2944d 100644 --- a/group12/247565311/week567_miniJVM/attr/StackMapTable.java +++ b/group12/247565311/week567_miniJVM/attr/StackMapTable.java @@ -9,7 +9,7 @@ public class StackMapTable extends AttributeInfo{ private String originalCode; public StackMapTable(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); + super(attrNameIndex, attrLen,AttributeInfo.STACK_MAP_TABLE); } public static StackMapTable parse(ByteCodeIterator iter){ diff --git a/group12/247565311/week567_miniJVM/clz/ClassFile.java b/group12/247565311/week567_miniJVM/clz/ClassFile.java index 91226364b8..5db5b1dba8 100644 --- a/group12/247565311/week567_miniJVM/clz/ClassFile.java +++ b/group12/247565311/week567_miniJVM/clz/ClassFile.java @@ -7,65 +7,48 @@ import structure.week1.ArrayList; public class ClassFile { - - private int minorVersion; - private int majorVersion; - - private AccessFlag accessFlag; - private ClassIndex clzIndex; - private ConstantPool pool; - - + public int minorVersion,majorVersion; + private AccessFlag accessFlag = null; + private ClassIndex clzIndex = null; + private ConstantPool constPool = null; + private ArrayList methods = null; + private ArrayList fields = null; + public ClassIndex getClzIndex() { return clzIndex; } + public void setClzIndex(ClassIndex clz){ + clzIndex = clz; + } public AccessFlag getAccessFlag() { return accessFlag; } - public void setAccessFlag(AccessFlag accessFlag) { - this.accessFlag = accessFlag; - } - - - - public ConstantPool getConstantPool() { - return pool; + public void setAccessFlag(AccessFlag acsFlag){ + accessFlag = acsFlag; + } + public ConstantPool getConstantPool() { + return constPool; } + public void setConstantPool(ConstantPool pool){ + constPool = pool; + } public int getMinorVersion() { return minorVersion; } - public void setMinorVersion(int minorVersion) { - this.minorVersion = minorVersion; - } public int getMajorVersion() { return majorVersion; } - public void setMajorVersion(int majorVersion) { - this.majorVersion = majorVersion; - } - public void setConstPool(ConstantPool pool) { - this.pool = pool; - - } - public void setClassIndex(ClassIndex clzIndex) { - this.clzIndex = clzIndex; - } - - - - + public void setVersion(int minor,int major){ + minorVersion = minor; + majorVersion = major; + } public void print(){ - if(this.accessFlag.isPublicClass()){ - System.out.println("Access flag : public "); + System.out.println("Access flag:public"); } System.out.println("Class Name:"+ getClassName()); - System.out.println("Super Class Name:"+ getSuperClassName()); - - } - private String getClassName(){ int thisClassIndex = this.clzIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); @@ -76,9 +59,18 @@ private String getSuperClassName(){ return superClass.getClassName(); } public ArrayList getMethods() { - return null; + return methods; } public ArrayList getFields() { - return null; + return fields; + } + public void setClassIndex(ClassIndex parseClassIndex) { + clzIndex = parseClassIndex; + } + public void setFields(ArrayList parseFields) { + fields = parseFields; + } + public void setMethods(ArrayList parseMethods) { + methods = parseMethods; } } diff --git a/group12/247565311/week567_miniJVM/constant/ConstantPool.java b/group12/247565311/week567_miniJVM/constant/ConstantPool.java index fb35f6c253..23c1c32dce 100644 --- a/group12/247565311/week567_miniJVM/constant/ConstantPool.java +++ b/group12/247565311/week567_miniJVM/constant/ConstantPool.java @@ -4,19 +4,13 @@ import java.util.List; public class ConstantPool { - private List constantInfos = new ArrayList(); - - public ConstantPool(){ } public void addConstantInfo(ConstantInfo info){ - this.constantInfos.add(info); - } - public ConstantInfo getConstantInfo(int index){ return this.constantInfos.get(index); } diff --git a/group12/247565311/week567_miniJVM/constant/InfoFactory.java b/group12/247565311/week567_miniJVM/constant/InfoFactory.java new file mode 100644 index 0000000000..8c8bdc12f4 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/InfoFactory.java @@ -0,0 +1,54 @@ +package week567_miniJVM.constant; +import week567_miniJVM.loader.ByteCodeIterator; +public class InfoFactory{ + private static InfoFactory infoFact = new InfoFactory(); + public static InfoFactory Invoke(){ + return infoFact; + } + public ConstantInfo getInfoObj(int tag,ByteCodeIterator iter,ConstantPool pool){ + switch(tag){ + case 1:{ + UTF8Info info = new UTF8Info(pool); + info.setLength(iter.nextU2ToInt()); + info.setValue(iter.nextUxToHexString(info.getLength())); + return info;} + case 7:{ + ClassInfo info = new ClassInfo(pool); + info.setUtf8Index(iter.nextU2ToInt()); + return info; } + case 8:{ + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + return info;} + case 9:{ + FieldRefInfo info = new FieldRefInfo(pool); + info.setClassInfoIndex(iter.nextU2ToInt()); + info.setNameAndTypeIndex(iter.nextU2ToInt()); + return info;} + case 10:{ + MethodRefInfo info = new MethodRefInfo(pool); + info.setClassInfoIndex(iter.nextU2ToInt()); + info.setNameAndTypeIndex(iter.nextU2ToInt()); + return info;} + case 12:{ + NameAndTypeInfo info = new NameAndTypeInfo(pool); + info.setIndex1(iter.nextU2ToInt()); + info.setIndex2(iter.nextU2ToInt()); + return info;} + default: + new RuntimeException("tag 为"+tag+" 的常亮项尚不支持!").printStackTrace(); + break; + } + return null; + } +} + + + + + + + + + + diff --git a/group12/247565311/week567_miniJVM/constant/UTF8Info.java b/group12/247565311/week567_miniJVM/constant/UTF8Info.java index ac2341bda9..40dbb7f126 100644 --- a/group12/247565311/week567_miniJVM/constant/UTF8Info.java +++ b/group12/247565311/week567_miniJVM/constant/UTF8Info.java @@ -26,7 +26,4 @@ public String getValue() { public void setValue(String value) { this.value = value; } - - - } diff --git a/group12/247565311/week567_miniJVM/field/Field.java b/group12/247565311/week567_miniJVM/field/Field.java index 47eac5a308..dd7510510a 100644 --- a/group12/247565311/week567_miniJVM/field/Field.java +++ b/group12/247565311/week567_miniJVM/field/Field.java @@ -1,33 +1,24 @@ package week567_miniJVM.field; +import structure.week1.ArrayList; import week567_miniJVM.constant.ConstantPool; -import week567_miniJVM.constant.UTF8Info; import week567_miniJVM.loader.ByteCodeIterator; - - public class Field { - private int accessFlag; - private int nameIndex; - private int descriptorIndex; - - - + private int accessFlag,nameIndex,descIndex; private ConstantPool pool; - - public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { - + public Field( int accessFlag, int nameIndex, int descIndex,ConstantPool pool) { this.accessFlag = accessFlag; this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; + this.descIndex = descIndex; this.pool = pool; } - - - - - public static Field parse(ConstantPool pool,ByteCodeIterator iter){ - - return null; + public void parse(ConstantPool pool,ByteCodeIterator iter){ + int propNum = iter.nextU2ToInt(); + while(propNum>0){ + propNum -= 1; + int prop = iter.nextU2ToInt(); + // TODO + } + return ; } - } \ No newline at end of file diff --git a/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java b/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java index d38345b3fe..a3cf1f4578 100644 --- a/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java +++ b/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java @@ -1,20 +1,38 @@ package week567_miniJVM.loader; public class ByteCodeIterator { - + private byte[] bytes = null; + int index = 0; + public ByteCodeIterator(byte[] _byte){ + bytes = _byte; + } + public void skip(int i){ + index += i; + } + public int nextU1ToInt(){ + byte a = bytes[index]; + System.out.print(a); + index += 1; + return (int)(a&0xff); + } public int nextU2ToInt() { - // TODO �Զ����ɵķ������ - return 0; + return nextU1ToInt()*256+nextU1ToInt(); } public int nextU4ToInt() { - // TODO �Զ����ɵķ������ - return 0; + return nextU1ToInt()*256*256*256+nextU1ToInt()*256*256+nextU1ToInt()*256+nextU1ToInt(); } public String nextUxToHexString(int len) { - // TODO �Զ����ɵķ������ - return null; + String res = ""; + while(len>0){ + len -= 1; + int a = nextU1ToInt(); + res += (char)(a&0xff); + } + return res; } - + public boolean hasNext(){ + return index clzPaths = new ArrayList(); - public byte[] readBinaryCode(String className) throws Exception { + public ClassFile loadClass(String className){ + + byte[] bytes = readBinaryCode(className); + ClassFile clzFile = new ClassFileParser().parse(bytes); + + return clzFile; + } + public byte[] readBinaryCode(String className) { for(String s:clzPaths){ String filename = s+className+".class"; File file = new File(filename); @@ -20,32 +26,26 @@ public byte[] readBinaryCode(String className) throws Exception { } return null; } - public ClassFile loadClass(String className){ - return null; - } - private byte[] loadClassFile(String clzFileName) throws Exception { + private byte[] loadClassFile(String clzFileName) { File file = new File(clzFileName); long filelength = file.length(); byte[]res = null; - if(filelength>Integer.MAX_VALUE)throw new IOException("�ļ�����"); + if(filelength>Integer.MAX_VALUE) new IOException("���ļ�����").printStackTrace(); try { FileInputStream fileinput = new FileInputStream(file); res = new byte[(int) filelength]; int offset=0,length=0; while(offset-1)) offset += length; - fileinput.close(); - } catch (FileNotFoundException e) { + if(fileinput!=null)fileinput.close(); + } catch (Exception e) { e.printStackTrace(); } return res; } - public void addClassPath(String path) { clzPaths.add(path); } - - public String getClassPath(){ String res = ""; int size = clzPaths.size(); diff --git a/group12/247565311/week567_miniJVM/test/ClassFileLoaderTest.java b/group12/247565311/week567_miniJVM/loader/ClassFileLoaderTest.java similarity index 93% rename from group12/247565311/week567_miniJVM/test/ClassFileLoaderTest.java rename to group12/247565311/week567_miniJVM/loader/ClassFileLoaderTest.java index ed81eaa399..c235413b3b 100644 --- a/group12/247565311/week567_miniJVM/test/ClassFileLoaderTest.java +++ b/group12/247565311/week567_miniJVM/loader/ClassFileLoaderTest.java @@ -1,7 +1,7 @@ -package week567_miniJVM.test; +package week567_miniJVM.loader; + import structure.week1.ArrayList; -import structure.week1.List; import week567_miniJVM.clz.ClassFile; import week567_miniJVM.clz.ClassIndex; import week567_miniJVM.constant.ClassInfo; @@ -19,23 +19,15 @@ import org.junit.Test; public class ClassFileLoaderTest { - private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "F:\\code_language\\demo\\Homework\\bin\\week567_miniJVM\\test"; + private static final String FULL_QUALIFIED_CLASS_NAME = "EmployeeV1.class"; + static String path1 = "F:\\code_language\\demo\\Homework\\bin\\week567_miniJVM\\test\\"; static String path2 = "C:\temp"; - static ClassFile clzFile = null; - static { - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; - - clzFile = loader.loadClass(className); - clzFile.print(); - } - - @Before - public void setUp() throws Exception { + public void setUp() throws Exception { + int �� = 1; + �� += 1; + System.out.print(��); } @After public void tearDown() throws Exception { @@ -59,7 +51,8 @@ public void testClassFileLength() { } catch (Exception e) { e.printStackTrace(); } - // 这里断言.class文件的字节数 + // �������.class�ļ����ֽ��� + System.out.print(byteCodes.length); Assert.assertEquals(267, byteCodes.length); } @Test @@ -91,8 +84,17 @@ private String byteToHexString(byte[] codes ){ return buffer.toString(); } /** - * miniJVM第二次作业测试用例 + * miniJVM�ڶ�����ҵ�������� */ + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week567_miniJVM.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + clzFile.print(); + } @Test public void testVersion(){ Assert.assertEquals(0, clzFile.getMinorVersion()); @@ -140,7 +142,7 @@ public void testConstantPool(){ Assert.assertEquals(9, nameAndType.getIndex1()); Assert.assertEquals(14, nameAndType.getIndex2()); } - // 随机抽查一个 + // ������һ�� { MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); Assert.assertEquals(1, methodRef.getClassInfoIndex()); @@ -160,7 +162,7 @@ public void testClassIndex(){ Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } /** - * miniJVM第三次作业测试用例 + * miniJVM��������ҵ�������� */ @Test public void testReadFields(){ @@ -223,4 +225,4 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } -} \ No newline at end of file +} diff --git a/group12/247565311/week567_miniJVM/loader/ClassFileParser.java b/group12/247565311/week567_miniJVM/loader/ClassFileParser.java index 5a23889b50..c3858dbaf6 100644 --- a/group12/247565311/week567_miniJVM/loader/ClassFileParser.java +++ b/group12/247565311/week567_miniJVM/loader/ClassFileParser.java @@ -1,44 +1,91 @@ package week567_miniJVM.loader; -import java.io.UnsupportedEncodingException; - +import structure.week1.ArrayList; import week567_miniJVM.clz.AccessFlag; import week567_miniJVM.clz.ClassFile; import week567_miniJVM.clz.ClassIndex; -import week567_miniJVM.constant.ClassInfo; +import week567_miniJVM.constant.ConstantInfo; import week567_miniJVM.constant.ConstantPool; -import week567_miniJVM.constant.FieldRefInfo; -import week567_miniJVM.constant.MethodRefInfo; -import week567_miniJVM.constant.NameAndTypeInfo; +import week567_miniJVM.constant.InfoFactory; import week567_miniJVM.constant.NullConstantInfo; -import week567_miniJVM.constant.StringInfo; -import week567_miniJVM.constant.UTF8Info; - -public class ClassFileParser { +import week567_miniJVM.field.Field; +import week567_miniJVM.method.Method; - public ClassFile parse(byte[] codes) { - - - - return null; +public class ClassFileParser { + public ClassFile parse(byte[] bytes) { + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(bytes); + if(!"cafebabe".equals(iter.nextUxToHexString(4))) return null; + + clzFile.setVersion(iter.nextU2ToInt(),iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstantPool(pool); + + clzFile.setAccessFlag(parseAccessFlag(iter)); + clzFile.setClassIndex(parseClassIndex(iter)); + + int collectionNum = iter.nextU2ToInt(); + iter.skip(collectionNum*2); + + clzFile.setFields(parseFields(iter,pool)); + clzFile.setMethods(parseMethods(clzFile,iter)); + return clzFile; } - - private AccessFlag parseAccessFlag(ByteCodeIterator iter) { - - return null; + + private ConstantPool parseConstantPool(ByteCodeIterator iter){ + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + int lenpool = iter.nextU2ToInt(); + while(lenpool>1){ + lenpool -= 1; + int tag = iter.nextU1ToInt(); + ConstantInfo info = InfoFactory.Invoke().getInfoObj(tag,iter,pool); + pool.addConstantInfo(info); + } + return pool; } - - private ClassIndex parseClassInfex(ByteCodeIterator iter) { - - return null; - + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag caflag = new AccessFlag(iter.nextU2ToInt()); + return caflag; } - - private ConstantPool parseConstantPool(ByteCodeIterator iter) { - - return null; + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex clzIndex = new ClassIndex(); + clzIndex.setThisClassIndex(iter.nextU2ToInt()); + clzIndex.setSuperClassIndex(iter.nextU2ToInt()); + return clzIndex; } - + private ArrayList parseFields(ByteCodeIterator iter,ConstantPool pool){ + ArrayList fields = new ArrayList(); + int fieldNum = iter.nextU2ToInt(); + while(fieldNum>0){ + fieldNum -= 1; + int accflag = iter.nextU2ToInt(); // 例如是public + int nameIndex = iter.nextU2ToInt();// 指向常量池的入口 + int descIndex = iter.nextU2ToInt(); // 指向常量池的入口 + Field field = new Field(accflag,nameIndex,descIndex,pool); + field.parse(pool,iter); + fields.add(field); + } + return fields; + } + + private ArrayList parseMethods(ClassFile clzFile,ByteCodeIterator iter){ + ArrayList methods = new ArrayList(); + int methodNum = iter.nextU2ToInt(); + while(methodNum>0){ + methodNum -= 1; + int accflag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + Method method = new Method(clzFile,accflag,nameIndex,descIndex); + method.parse(clzFile,iter); + methods.add(method); + } + return methods; + } } diff --git a/group12/247565311/week567_miniJVM/method/Method.java b/group12/247565311/week567_miniJVM/method/Method.java index aadd29e9a6..ceabffec1b 100644 --- a/group12/247565311/week567_miniJVM/method/Method.java +++ b/group12/247565311/week567_miniJVM/method/Method.java @@ -1,58 +1,51 @@ package week567_miniJVM.method; - import week567_miniJVM.clz.ClassFile; -import week567_miniJVM.attr.AttributeInfo; -import week567_miniJVM.attr.CodeAttr; -import week567_miniJVM.constant.ConstantPool; +import week567_miniJVM.constant.ConstantInfo; import week567_miniJVM.constant.UTF8Info; import week567_miniJVM.loader.ByteCodeIterator; - - +import week567_miniJVM.attr.AttrFactory; +import week567_miniJVM.attr.AttributeInfo; +import week567_miniJVM.attr.CodeAttr; public class Method { - - private int accessFlag; - private int nameIndex; - private int descriptorIndex; - + private int accessFlag,nameIndex,descIndex; private CodeAttr codeAttr; - private ClassFile clzFile; - public ClassFile getClzFile() { return clzFile; } - + public int getAccessFlag(){ + return accessFlag; + } public int getNameIndex() { return nameIndex; } public int getDescriptorIndex() { - return descriptorIndex; + return descIndex; } - public CodeAttr getCodeAttr() { return codeAttr; } - public void setCodeAttr(CodeAttr code) { this.codeAttr = code; } - - public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descIndex) { this.clzFile = clzFile; this.accessFlag = accessFlag; this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; + this.descIndex = descIndex; } - - - - - public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ - return null; - + public void parse(ClassFile clzFile, ByteCodeIterator iter){ + int attributeNum = iter.nextU2ToInt(); + while(attributeNum>0){ + attributeNum -= 1; + AttributeInfo attrinfo = AttrFactory.Instance().parse(clzFile, iter); + if(attrinfo == null) continue; + + + } } } diff --git a/group12/247565311/week567_miniJVM/test/EmployeeV1.java b/group12/247565311/week567_miniJVM/test/EmployeeV1.java index b9855461ae..bfa4460096 100644 --- a/group12/247565311/week567_miniJVM/test/EmployeeV1.java +++ b/group12/247565311/week567_miniJVM/test/EmployeeV1.java @@ -1,5 +1,18 @@ package week567_miniJVM.test; public class EmployeeV1 { - + private int age; + private String name; + public void setAge(int _age){ + age = _age; + } + public int getAge(){ + return age; + } + public void setName(String _name){ + name = _name; + } + public String getName(){ + return name; + } } diff --git a/group12/247565311/week567_miniJVM/util/Util.java b/group12/247565311/week567_miniJVM/util/Util.java index c10eaee6f2..9c7baeb915 100644 --- a/group12/247565311/week567_miniJVM/util/Util.java +++ b/group12/247565311/week567_miniJVM/util/Util.java @@ -5,9 +5,6 @@ public static int byteToInt(byte[] codes){ String s1 = byteToHexString(codes); return Integer.valueOf(s1, 16).intValue(); } - - - public static String byteToHexString(byte[] codes ){ StringBuffer buffer = new StringBuffer(); for(int i=0;i Date: Sat, 15 Apr 2017 23:12:59 -0700 Subject: [PATCH 041/151] jvm homework, Fields and Methods parsing --- .../coderising/jvm/attr/AttributeInfo.java | 48 +++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 94 +++++++++ .../attr/InvalidAttributeInfoException.java | 7 + .../coderising/jvm/attr/LineNumberTable.java | 53 +++++ .../jvm/attr/LocalVariableItem.java | 71 +++++++ .../jvm/attr/LocalVariableTable.java | 40 ++++ .../coderising/jvm/attr/StackMapTable.java | 30 +++ .../src/com/coderising/jvm/clz/ClassFile.java | 24 ++- .../coderising/jvm/constant/ConstantInfo.java | 1 - .../jvm/constant/ConstantInfoFactory.java | 4 +- .../coderising/jvm/constant/ConstantPool.java | 8 + .../src/com/coderising/jvm/field/Field.java | 50 +++++ .../coderising/jvm/interfaze/Interfaze.java | 5 + .../interfaze/InvalidInterfaceException.java | 7 + .../jvm/loader/ByteCodeIterator.java | 23 ++- .../jvm/loader/ClassFileParser.java | 101 ++++++++-- .../method/InvalidMethodInfoException.java | 7 + .../src/com/coderising/jvm/method/Method.java | 87 +++++++++ .../jvm/test/ClassFileloaderTest.java | 81 +++++++- .../jvm/test/ClassFileloaderTest2.java | 52 +++++ .../coding/basic/stack/expr/InfixExpr.java | 184 ++++++++++++++++++ .../basic/stack/expr/InfixExprTest.java | 60 ++++++ group17/article/20170409-20170416.md | 56 ++++++ 23 files changed, 1069 insertions(+), 24 deletions(-) create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/InvalidAttributeInfoException.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group17/1282579502/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group17/1282579502/src/com/coderising/jvm/field/Field.java create mode 100644 group17/1282579502/src/com/coderising/jvm/interfaze/Interfaze.java create mode 100644 group17/1282579502/src/com/coderising/jvm/interfaze/InvalidInterfaceException.java create mode 100644 group17/1282579502/src/com/coderising/jvm/method/InvalidMethodInfoException.java create mode 100644 group17/1282579502/src/com/coderising/jvm/method/Method.java create mode 100644 group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest2.java create mode 100644 group17/1282579502/src/com/coding/basic/stack/expr/InfixExpr.java create mode 100644 group17/1282579502/src/com/coding/basic/stack/expr/InfixExprTest.java create mode 100644 group17/article/20170409-20170416.md diff --git a/group17/1282579502/src/com/coderising/jvm/attr/AttributeInfo.java b/group17/1282579502/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..1e4c513330 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,48 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +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; + } + + public static AttributeInfo parse(ClassFile file, ByteCodeIterator iter) throws InvalidAttributeInfoException{ + AttributeInfo attrInfo = null; + int attributeType = iter.getNextNBytesInteger(2); + String attributeTag = file.getConstantPool().getUTF8String(attributeType); + System.out.println("attribute type: " + attributeType + " utf8 val: " + file.getConstantPool().getUTF8String(attributeType)); + + if(attributeTag.equals(CODE)){ + System.out.println("about to parse CODE attribute"); + //ClassFile clzFile, ByteCodeIterator iter, int attributeNameIndex + attrInfo = CodeAttr.parse(file, iter, attributeType); + } + else if(attributeTag.equals(LINE_NUM_TABLE)){ + System.out.println("about to parse LINE_NUM_TABLE attribute"); + attrInfo = LineNumberTable.parse(iter); + } + else if(attributeTag.equals(LOCAL_VAR_TABLE)){ + System.out.println("about to parse LOCAL_VAR_TABLE attribute"); + attrInfo = LocalVariableTable.parse(iter, file, attributeType); + } + else{ + System.out.println("about to throw attribute"); + throw new InvalidAttributeInfoException("Unimplemented attribute exception."); + } + + return attrInfo; + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/attr/CodeAttr.java b/group17/1282579502/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..12d151d575 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,94 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; +import com.coderising.jvm.method.InvalidMethodInfoException; + + +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 attributeNameIndex) throws InvalidAttributeInfoException{ + System.out.println("parsing CodeAttr..."); + + int attributeLength = iter.getNextNBytesInteger(4); + int maxStack = iter.getNextNBytesInteger(2); + int maxLocalVar = iter.getNextNBytesInteger(2); + int codeLength = iter.getNextNBytesInteger(4); + + + System.out.println("attribute length: " + attributeLength); + System.out.println("max stack: " + maxStack); + System.out.println("max local variable: " + maxLocalVar); + System.out.println("code length: " + codeLength); + + String realCode = iter.getNextNHexString(codeLength); + System.out.println("real cdoe: " + realCode); + + int exceptionCount = iter.getNextNBytesInteger(2); + System.out.println("exception count: " + exceptionCount); + if(exceptionCount>0){ + throw new InvalidAttributeInfoException("Exception parser un-implemented."); + } + //int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code + CodeAttr code = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocalVar, codeLength, realCode); + + int subAttributeCount = iter.getNextNBytesInteger(2); + System.out.println("sub attribute count : " + subAttributeCount); + 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 attributeLength = iter.getNextNBytesInteger(4); + int lineNumberTableLength = iter.getNextNBytesInteger(2); + System.out.println("attribute length: " + attributeLength); + System.out.println("line number table length: " + lineNumberTableLength); + LineNumberTable table = new LineNumberTable(attributeLength, lineNumberTableLength); + for(int i = 0; i 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, ClassFile clz, int nameIndex){ + LocalVariableTable attrInfo = null; + int attributeLength = iter.getNextNBytesInteger(4); + int localVarTableLength = iter.getNextNBytesInteger(2); + System.out.println("attribute length: " + attributeLength); + System.out.println("local variable table length: " + localVarTableLength); + attrInfo = new LocalVariableTable(nameIndex, attributeLength); + for(int i = 0;i fields; + private List methods; public ClassIndex getClzIndex() { return clzIndex; @@ -49,8 +55,6 @@ public void setClassIndex(ClassIndex clzIndex) { } - - public void print(){ if(this.accessFlag.isPublicClass()){ @@ -72,4 +76,20 @@ private String getSuperClassName(){ ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } + + public void setFields(List fields){ + this.fields = fields; + } + + public void setMethods(List methods){ + this.methods = methods; + } + + public List getFields(){ + return fields; + } + + public List getMethods(){ + return methods; + } } diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java index b99ed30fbf..4ddac90612 100755 --- a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfo.java @@ -26,5 +26,4 @@ public ConstantPool getConstantPool() { public ConstantInfo getConstantInfo(int index){ return this.constantPool.getConstantInfo(index); } - } diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java index 01df38c682..ce35409add 100644 --- a/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantInfoFactory.java @@ -16,7 +16,7 @@ public ConstantInfoFactory(ByteCodeIterator iter, ConstantPool pool){ public void fillNextConstantInfo() throws InvalidConstantInfoTypeException, UnsupportedEncodingException{ int constantIdentifier = iter.getNextByte(); ConstantInfo var = null; - System.out.println("constant identifyer: " + constantIdentifier); + //System.out.println("constant identifyer: " + constantIdentifier); var = classify(constantIdentifier); pool.addConstantInfo(var); } @@ -27,7 +27,7 @@ public ConstantInfo classify(int constantInfoTypeId) throws InvalidConstantInfoT case ConstantInfo.CLASS_INFO: ClassInfo classInfo = new ClassInfo(pool); byte[] utf8Index = iter.getNextNBytes(2); - System.out.println("constant classInfo: utf index: " + Util.byteToInt(utf8Index)); + //System.out.println("constant classInfo: utf index: " + Util.byteToInt(utf8Index)); classInfo.setUtf8Index(Util.byteToInt(utf8Index)); ret = classInfo; diff --git a/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java b/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java index 9a1a998f41..59ad734f25 100755 --- a/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group17/1282579502/src/com/coderising/jvm/constant/ConstantPool.java @@ -26,4 +26,12 @@ public String getUTF8String(int index){ public int getSize() { return this.constantInfos.size() -1; } + + public String toString(){ + StringBuilder sb = new StringBuilder(); + for(int i = 0; i attributeList = new ArrayList<>(); + for(int i = 0; i0){ + throw new InvalidAttributeInfoException("Attribute infomation is NOT valid."); + } + Field newField = new Field(accessFlag, nameIndex, descriptorIndex,pool); + return newField; + } + + public String toString(){ + return pool.getUTF8String(nameIndex) + ":" +pool.getUTF8String( descriptorIndex); + } + +} diff --git a/group17/1282579502/src/com/coderising/jvm/interfaze/Interfaze.java b/group17/1282579502/src/com/coderising/jvm/interfaze/Interfaze.java new file mode 100644 index 0000000000..7d1f90c030 --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/interfaze/Interfaze.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.interfaze; + +public class Interfaze { + +} diff --git a/group17/1282579502/src/com/coderising/jvm/interfaze/InvalidInterfaceException.java b/group17/1282579502/src/com/coderising/jvm/interfaze/InvalidInterfaceException.java new file mode 100644 index 0000000000..b5eed64afc --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/interfaze/InvalidInterfaceException.java @@ -0,0 +1,7 @@ +package com.coderising.jvm.interfaze; + +public class InvalidInterfaceException extends Exception{ + public InvalidInterfaceException(String message){ + super(message); + } +} diff --git a/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java index f312b513ac..b34c2c6736 100755 --- a/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group17/1282579502/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -1,5 +1,7 @@ package com.coderising.jvm.loader; +import com.coderising.jvm.util.Util; + public class ByteCodeIterator { byte[] source = null; @@ -50,7 +52,26 @@ public String getNextNHexString(int n){ return sb.toString(); } - + + public String peekNextNHex(int n){ + String val = getNextNHexString(n); + backOffNBytes(n); + return val; + } + + public void backOffNBytes(int n){ + if(n < currentPos){ + currentPos -=n; + } + else{ + System.err.println("Don't have enough bytes."); + } + } + + public int getNextNBytesInteger(int n){ + byte[] barray = getNextNBytes(n); + return Util.byteToInt(barray); + } public static void printByteInNumber(byte b){ diff --git a/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java index 7c5809efec..c168129abc 100755 --- a/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group17/1282579502/src/com/coderising/jvm/loader/ClassFileParser.java @@ -1,7 +1,11 @@ package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import com.coderising.jvm.attr.InvalidAttributeInfoException; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; @@ -16,6 +20,11 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.interfaze.Interfaze; +import com.coderising.jvm.interfaze.InvalidInterfaceException; +import com.coderising.jvm.method.InvalidMethodInfoException; +import com.coderising.jvm.method.Method; public class ClassFileParser { ClassFile clz = null; @@ -24,29 +33,89 @@ public ClassFile parse(byte[] codes) { ByteCodeIterator iter = new ByteCodeIterator(codes); String magicHex = iter.getNextNHexString(4); System.out.println("Magic Number: "+magicHex); - - String minorHex = iter.getNextHexString() + iter.getNextHexString(); - int minorVersionInt = Integer.parseInt(minorHex, 16); - String majorHex = iter.getNextHexString() + iter.getNextHexString(); - int majorVersionInt = Integer.parseInt(majorHex, 16); - clz.setMajorVersion(majorVersionInt);clz.setMinorVersion(minorVersionInt); - System.out.println("Major version: " + majorVersionInt + " minor version: " + minorVersionInt); - clz.setConstPool(parseConstantPool(iter)); - fillClassInfo(clz, clz.getConstantPool()); + try{ + String minorHex = iter.getNextHexString() + iter.getNextHexString(); + int minorVersionInt = Integer.parseInt(minorHex, 16); + String majorHex = iter.getNextHexString() + iter.getNextHexString(); + int majorVersionInt = Integer.parseInt(majorHex, 16); + clz.setMajorVersion(majorVersionInt);clz.setMinorVersion(minorVersionInt); + System.out.println("Major version: " + majorVersionInt + " minor version: " + minorVersionInt); + clz.setConstPool(parseConstantPool(iter)); + fillClassInfo(clz, clz.getConstantPool()); + System.out.println(iter.peekNextNHex(8)); + parseAccessFlag(iter); + parseClassInfex(iter);parseClassInfex(iter); + parseInterface(iter); + parseFields(iter); + parseMethods(iter); + } + catch(Exception e){ + e.printStackTrace(); + } return clz; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + ConstantPool cp = clz.getConstantPool(); + int visitFlagIndex = iter.getNextNBytesInteger(2); + System.out.println("visit flag index: " + visitFlagIndex + " variable value: " + cp.getUTF8String(visitFlagIndex)); return null; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { - + int classInfIndex = iter.getNextNBytesInteger(2); + System.out.println("class info: " + classInfIndex); return null; } + private List parseInterface(ByteCodeIterator iter) throws InvalidInterfaceException{ + int interfaceCount = iter.getNextNBytesInteger(2); + if(interfaceCount>0){ + throw new InvalidInterfaceException("Unimplemented interface parser: " + interfaceCount); + } + return null; + } + + private void parseFields(ByteCodeIterator iter){ + int fieldsCount = iter.getNextNBytesInteger(2); + System.out.println("Fields count: " + fieldsCount); + List fields = new LinkedList<>(); + for(int i = 0; i methods = new ArrayList<>(); + for(int i = 0; i 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); + } - } diff --git a/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest2.java b/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest2.java new file mode 100644 index 0000000000..a0e42c0f0e --- /dev/null +++ b/group17/1282579502/src/com/coderising/jvm/test/ClassFileloaderTest2.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + + + + + +public class ClassFileloaderTest2 { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + static String path1 = "/Users/erlisuo/Documents/workspace/codeRising2017working/1282579502/bin"; + static String path3 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static ClassFileLoader loader = null; + static { + loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + //clzFile.print(); + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + +} diff --git a/group17/1282579502/src/com/coding/basic/stack/expr/InfixExpr.java b/group17/1282579502/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..2d70a2ec02 --- /dev/null +++ b/group17/1282579502/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,184 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import javafx.util.converter.NumberStringConverter; + +public class InfixExpr { + String expr = null; + Map priorityMap = null; + List exprTokens = null; + public InfixExpr(String expr) { + priorityMap = new HashMap(); + init(); + this.expr = expr; + exprTokens = parse(); + } + + public void init(){ + priorityMap.put('+', 0); + priorityMap.put('-', 0); + priorityMap.put('*', 1); + priorityMap.put('/', 1); + } + + public float evaluate() { + Stack operatorStack = new Stack<>(); + Stack operandStack = new Stack<>(); + + Float operandOne, operandTwo; + + int index = 0; + + while(index < exprTokens.size()){ + String cc = exprTokens.get(index); + try{ + if(isFloat(cc)){ + System.out.println("push operand: " + cc); + operandStack.push(Float.parseFloat(cc)); + System.out.println("peek: " + operandStack.peek()); + + } + else if(priorityMap.get(cc.charAt(0)) != null){ + char c = cc.charAt(0); + if(operatorStack.isEmpty()){ + System.out.println("push operator: " + cc); + operatorStack.push(c); + } + else{ + int preOperatorPriority = getPriority(operatorStack.peek()); + int curOperatorPriority = getPriority(c); + if(curOperatorPriority <= preOperatorPriority){ + //do precalculation first + operandTwo = operandStack.pop(); + operandOne = operandStack.pop(); + char operator = operatorStack.pop(); + float result = doCalculation(operandOne, operandTwo, operator); + + operandStack.push(result); + operatorStack.push(c); + } + else{ + System.out.println("push operator: " + cc); + operatorStack.push(c); + } + } + } + else{ + throw new Exception("Unsupported character: " + cc); + } + } + catch(Exception e){ + e.printStackTrace(); + } + index ++; + } + System.out.println("dumpping operator stack:"); + dumpStack(operatorStack); + System.out.println("dumpping operand stack:"); + dumpStack(operandStack); + try{ + while(!operatorStack.isEmpty()){ + operandTwo = operandStack.pop(); + operandOne = operandStack.pop(); + char operator = operatorStack.pop(); + float result = doCalculation(operandOne, operandTwo, operator); + + operandStack.push(result); + } + }catch(Exception e){ + e.printStackTrace(); + } + + if(operandStack.size() > 1){ + System.err.println("More than one result reminded in operands stack."); + } + return operandStack.pop(); + } + + private float doCalculation(float operandOne, float operandTwo, char operator) throws Exception{ + System.out.println("operand 1: " + operandOne + " operand 2: " + operandTwo + " operator: " + operator); + float result = 0f; + if(operator == '+'){ + result = operandOne + operandTwo; + } + else if(operator == '-'){ + result = operandOne - operandTwo; + } + else if(operator == '*'){ + result = operandOne * operandTwo; + } + else if(operator == '/'){ + result = operandOne / operandTwo; + } + else{ + throw new Exception("Unsupported operator"); + } + System.out.println("result: " + result); + return result; + } + + private int getPriority(Character c){ + return priorityMap.get(c); + } + + private boolean isFloat(String v){ + try{ + Float.parseFloat(v); + return true; + } + catch(Exception e){ + return false; + } + } + + private List parse(){ + List vals = new ArrayList<>(); + int p1 = 0; + int p2 = 1; + while(p2 Date: Sun, 16 Apr 2017 15:51:04 +0800 Subject: [PATCH 042/151] =?UTF-8?q?jvm=E7=AC=AC=E4=B8=89=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A,=20=E5=B1=9E=E6=80=A7=E6=96=B9=E6=B3=95=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/jvm/attr/AttributeInfo.java | 19 +++++ .../com/coding2017/jvm/attr/CodeAttr.java | 52 +++++++++++++ .../coding2017/jvm/attr/LineNumberTable.java | 46 +++++++++++ .../jvm/attr/LocalVariableItem.java | 49 ++++++++++++ .../jvm/attr/LocalVariableTable.java | 25 ++++++ .../coding2017/jvm/attr/StackMapTable.java | 29 +++++++ .../com/coding2017/jvm/bean/EmployeeV1.java | 1 + .../com/coding2017/jvm/clz/ClassFile.java | 36 +++++++++ .../java/com/coding2017/jvm/field/Field.java | 32 ++++++++ .../jvm/loader/ByteCodeIterator.java | 8 ++ .../jvm/loader/ClassFileParser.java | 10 +++ .../com/coding2017/jvm/method/Method.java | 48 ++++++++++++ .../jvm/loader/ClassFileLoaderTest.java | 76 +++++++++++++++++++ 13 files changed, 431 insertions(+) create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableItem.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java create mode 100644 group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..2ec4931cac --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..a0a52ca70c --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java @@ -0,0 +1,52 @@ +package com.coding2017.jvm.attr; + +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.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) { + + return null; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..9449eafc1f --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java @@ -0,0 +1,46 @@ +package com.coding2017.jvm.attr; + +import com.coding2017.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTable extends AttributeInfo { + List 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) { + + return null; + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableItem.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..4ad18b0fd7 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableItem.java @@ -0,0 +1,49 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..41dfb68e87 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java @@ -0,0 +1,25 @@ +package com.coding2017.jvm.attr; + +import com.coding2017.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); + } + + public static LocalVariableTable parse(ByteCodeIterator iter) { + + return null; + } + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..a9fab7c2e8 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +package com.coding2017.jvm.attr; + +import com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java index 4fdddbb2eb..487793f448 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java @@ -3,6 +3,7 @@ public class EmployeeV1 { private String name; + private int age; public EmployeeV1(String name, int age) { diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java index 19c738f8d4..6d12e65d5b 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java @@ -2,6 +2,11 @@ import com.coding2017.jvm.constant.ClassInfo; import com.coding2017.jvm.constant.ConstantPool; +import com.coding2017.jvm.field.Field; +import com.coding2017.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; public class ClassFile { @@ -12,6 +17,9 @@ public class ClassFile { private ClassIndex clzIndex; private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + public ClassIndex getClzIndex() { return clzIndex; } @@ -53,6 +61,34 @@ public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } + public void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public List getMethods() { + return methods; + } + + public void setMethods(List methods) { + this.methods = methods; + } + public void print() { if (this.accessFlag.isPublicClass()) { diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java new file mode 100644 index 0000000000..3439d9c8bf --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java @@ -0,0 +1,32 @@ +package com.coding2017.jvm.field; + + +import com.coding2017.jvm.constant.ConstantPool; +import com.coding2017.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java index 566b251c32..3a3af964c5 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java @@ -35,4 +35,12 @@ public byte[] nextByteN(int n) { } return bytes; } + + public int nextU4ToInt() { + return ByteUtil.bytesToInt(nextByteN(4)); + } + + public String nextUxToHexString(int len) { + return ByteUtil.byteToHexString(nextByteN(len)); + } } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java index ff21b4fa0c..b684d1774d 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java @@ -30,6 +30,8 @@ public ClassFile parse(byte[] codes) { // this class and super class classFile.setClassIndex(parseClassInfex(iterator)); + parseInterfaces(iterator); + return classFile; } @@ -96,4 +98,12 @@ private ConstantInfo parseConstantInfo(ConstantPool constantPool, ByteCodeIterat } } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java new file mode 100644 index 0000000000..9969d5dcf0 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java @@ -0,0 +1,48 @@ +package com.coding2017.jvm.method; + +import com.coding2017.jvm.attr.CodeAttr; +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.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 static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + return null; + + } +} diff --git a/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java index c25f6f2c0f..d9dd2a22ff 100644 --- a/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java +++ b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java @@ -3,11 +3,15 @@ import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.clz.ClassIndex; import com.coding2017.jvm.constant.*; +import com.coding2017.jvm.field.Field; +import com.coding2017.jvm.method.Method; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.List; + import static org.junit.Assert.*; /** @@ -186,4 +190,76 @@ public void testClassIndex(){ 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); + } + } \ No newline at end of file From a1d23c39a6a024facea3f652b40cef52e7021513 Mon Sep 17 00:00:00 2001 From: sheng <1158154002@qq.com> Date: Sun, 16 Apr 2017 18:42:06 +0800 Subject: [PATCH 043/151] test06 --- .../1158154002/src/test05/stack/Stack.java | 10 +- .../src/test05/stack/StackUtil.java | 104 ++++++++++++------ .../1158154002/src/test06/expr/InfixExpr.java | 92 ++++++++++++++++ .../src/test06/expr/InfixExprTest.java | 45 ++++++++ 4 files changed, 212 insertions(+), 39 deletions(-) create mode 100644 group17/1158154002/src/test06/expr/InfixExpr.java create mode 100644 group17/1158154002/src/test06/expr/InfixExprTest.java diff --git a/group17/1158154002/src/test05/stack/Stack.java b/group17/1158154002/src/test05/stack/Stack.java index 1ce32a40e5..177a330f7c 100644 --- a/group17/1158154002/src/test05/stack/Stack.java +++ b/group17/1158154002/src/test05/stack/Stack.java @@ -2,18 +2,18 @@ import java.util.ArrayList; -public class Stack { - private ArrayList elementData = new ArrayList(); +public class Stack { + private ArrayList elementData = new ArrayList(); - public void push(Object o){ + public void push(T o){ elementData.add(o); } - public Object pop(){ + public T pop(){ return elementData.remove(size()-1); } - public Object peek(){ + public T peek(){ if (size()>0) { return elementData.get(size()-1); } else { diff --git a/group17/1158154002/src/test05/stack/StackUtil.java b/group17/1158154002/src/test05/stack/StackUtil.java index b999c82706..ead00078b6 100644 --- a/group17/1158154002/src/test05/stack/StackUtil.java +++ b/group17/1158154002/src/test05/stack/StackUtil.java @@ -71,43 +71,79 @@ public static Object[] getTop(Stack s,int len) { * @param s * @return */ - public static boolean isValidPairs(String s) { - Stack s1 = new Stack(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { - s1.push(c); - } - } - - Stack s2 = new Stack(); - for (int i = s.length() - 1; i >= 0; i--) { +// public static boolean isValidPairs(String s) { +// Stack s1 = new Stack(); +// for (int i = 0; i < s.length(); i++) { +// char c = s.charAt(i); +// if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { +// s1.push(c); +// } +// } +// +// Stack s2 = new Stack(); +// for (int i = s.length() - 1; i >= 0; i--) { +// char c = s.charAt(i); +// if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { +// s2.push(c); +// } +// } +// +// for (int i = 0; i < s1.size() / 2; i++) { +// char a = (char) s1.pop(); +// char b = (char) s2.pop(); +// if (a == '(' && b != ')') { +// return false; +// } else if (a == ')' && b != '(') { +// return false; +// } else if (a == '[' && b != ']') { +// return false; +// } else if (a == ']' && b != '[') { +// return false; +// } else if (a == '{' && b != '}') { +// return false; +// } else if (a == '}' && b != '{') { +// return false; +// } +// } +// +// return true; +// } + +public static boolean isValidPairs(String s){ + + Stack stack = new Stack(); + for(int i=0;i symbol = new Stack<>(); + Stack num = new Stack<>(); + + for (int i = 0; i < str.length; i++) { + num.push(Float.valueOf(str[i])); + } + + for (int i = 0; i < expr.length(); i++) { + char c = expr.charAt(i); + if (c == '+' || c == '-' || c == '*' || c == '/') { + symbol.push(c); + } + } + // 逆置 + StackUtil.reverse(symbol); + StackUtil.reverse(num); + + // 取数,符号计算 + float result = 0; + while (num.size() > 1) { + float a = num.pop(); + float b = num.pop(); + + char s1 = symbol.pop(); + char s2 = ' '; + if (symbol.size() > 0) { + s2 = symbol.pop(); + if (s1 == '*') { + result = a * b; + symbol.push(s2); + } else if (s1 == '/') { + result = a / b; + symbol.push(s2); + } else if (s2 != ' ') { + if (s2 == '*' || s2 == '/') { + if (s2 == '*') { + result = b * num.pop(); + } else if (s2 == '/') { + result = b / num.pop(); + } + if (s1 == '+') { + result = a + result; + } else if (s1 == '-') { + result = a - result; + } + } else { + if (s1 == '+') { + result = a + b; + symbol.push(s2); + } else if (s1 == '-') { + result = a - b; + symbol.push(s2); + } + } + } + num.push(result); + System.out.println(result); + } else { + if (s1 == '+') { + result = a + b; + } else if (s1 == '-') { + result = a - b; + } else if (s1 == '*') { + result = a * b; + } else if (s1 == '/') { + result = a / b; + } + System.out.println(result); + } + } + + return result; + } +} diff --git a/group17/1158154002/src/test06/expr/InfixExprTest.java b/group17/1158154002/src/test06/expr/InfixExprTest.java new file mode 100644 index 0000000000..5c03c1a06d --- /dev/null +++ b/group17/1158154002/src/test06/expr/InfixExprTest.java @@ -0,0 +1,45 @@ +package test06.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixExprTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } +// + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } +} From b86ed4bd02d6f14d784d1e6988d56a3a99c5c891 Mon Sep 17 00:00:00 2001 From: mengxz <82427129@qq.com> Date: Sun, 16 Apr 2017 19:29:39 +0800 Subject: [PATCH 044/151] homework ,diliverd at 17/4/9.complited --- .../coderising/jvm/attr/AttributeInfo.java | 3 +- .../com/coderising/jvm/attr/CodeAttr.java | 8 ++ .../coderising/jvm/attr/LineNumberTable.java | 10 ++ .../jvm/attr/LocalVariableItem.java | 10 -- .../jvm/attr/LocalVariableTable.java | 82 ++++++++++- .../coderising/jvm/attr/StackMapTable.java | 7 +- .../com/coderising/jvm/method/Method.java | 7 +- .../java/com/coding/basic/stack/Stack.java | 12 ++ .../com/coding/basic/stack/StackUtil.java | 130 ++++++++++++++++-- .../coding/basic/stack/expr/InfixExpr.java | 38 +++++ .../jvm/loader/ClassFileLoaderTest.java | 5 +- 11 files changed, 278 insertions(+), 34 deletions(-) delete mode 100644 group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java index f39a23dcf3..8fb9e91d57 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/AttributeInfo.java @@ -14,6 +14,7 @@ public abstract class AttributeInfo { int attrNameIndex;// u2 attribute_name_index int attrLen;// u4 attribute_length + public abstract String getType(); public AttributeInfo(int attrNameIndex, int attrLen) { this.attrNameIndex = attrNameIndex; this.attrLen = attrLen; @@ -30,7 +31,7 @@ public static AttributeInfo parse(ConstantPool pool, ByteCodeIterator itr) { case LINE_NUM_TABLE: return LineNumberTable.parse(pool, itr); case LOCAL_VAR_TABLE: - + return LocalVariableTable.parse(pool, itr); default: throw new RuntimeException( "attributeInfo exclude CodeAttr hasn't implemented"); diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java index 3011511ae4..1f9cfdc169 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/CodeAttr.java @@ -8,6 +8,7 @@ public class CodeAttr extends AttributeInfo { + private static String TYPE = CODE; private int maxStack;//u2 max_stack private int maxLocals;//u2 max_locals private int codeLenth;//u4 code_length @@ -43,6 +44,11 @@ public void addAttr(AttributeInfo a){ this.AttrList.add(a); } + @Override + public String getType() { + return TYPE; + } + public static CodeAttr parse(ConstantPool pool, ByteCodeIterator itr) { int attrNameIndex = itr.nextU2toInt(); int attrLen = itr.nextU4toInt(); @@ -118,4 +124,6 @@ public void setExceptionTableLength(int exceptionTableLength) { this.exceptionTableLength = exceptionTableLength; } + + } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java index 30b39988f0..4cce2e0368 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LineNumberTable.java @@ -8,6 +8,7 @@ public class LineNumberTable extends AttributeInfo { + private static String TYPE = LINE_NUM_TABLE; private int lineNumberTableLength; private List lineNumberTable = new ArrayList(); @@ -21,6 +22,10 @@ public void addLineNumberItem(LineNumberItem e) { this.lineNumberTable.add(e); } + @Override + public String getType() { + return TYPE; + } public static LineNumberTable parse(ConstantPool pool, ByteCodeIterator itr) { int attrNameIndex = itr.nextU2toInt(); int attrLen = itr.nextU4toInt(); @@ -33,6 +38,11 @@ public static LineNumberTable parse(ConstantPool pool, ByteCodeIterator itr) { return lineNumberTable; } + /** + * + * @author Meng + * + */ private static class LineNumberItem { @SuppressWarnings("unused") private int startPc; diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java deleted file mode 100644 index 74ca8df92e..0000000000 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.coderising.jvm.attr; - -public class LocalVariableItem extends AttributeInfo { - - public LocalVariableItem(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); - // TODO Auto-generated constructor stub - } - -} diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java index 2704149043..b5d5147a3f 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java @@ -1,17 +1,91 @@ package com.coderising.jvm.attr; +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + public class LocalVariableTable extends AttributeInfo { - private int localVarTableLength ;//u2 local_variable_table_length - - - private static class + private static String TYPE = LOCAL_VAR_TABLE; + private int localVarTableLength;// u2 local_variable_table_length + private List itemList = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen, + int localVarTableLength) { + super(attrNameIndex, attrLen); + this.localVarTableLength = localVarTableLength; + } + + public void addItemList(LocalVariableItem item) { + this.itemList.add(item); + } + + @Override + public String getType() { + return TYPE; + } + public static LocalVariableTable parse(ConstantPool pool, + ByteCodeIterator itr) { + int attrNameIndex = itr.nextU2toInt(); + int attrLen = itr.nextU4toInt(); + int localVarTableLength = itr.nextU2toInt(); + LocalVariableTable table = new LocalVariableTable(attrNameIndex, + attrLen, localVarTableLength); + for (int i = 0; i < localVarTableLength; i++) { + table.addItemList(LocalVariableItem.parse(pool, itr)); + } + return table; + } + + /** + * inner class + * + * @author Meng + * + */ + public static class LocalVariableItem { + @SuppressWarnings("unused") + private int startPc; + @SuppressWarnings("unused") + private int length; + @SuppressWarnings("unused") + private int nameIndex; + @SuppressWarnings("unused") + private int descriptorIndex; + @SuppressWarnings("unused") + private int index; + + public LocalVariableItem(int startPc, int length, int nameIndex, + int descriptorIndex, int index) { + super(); + this.startPc = startPc; + this.length = length; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.index = index; + } + + public static LocalVariableItem parse(ConstantPool pool, + ByteCodeIterator itr) { + int startPc = itr.nextU2toInt(); + int length = itr.nextU2toInt(); + int nameIndex = itr.nextU2toInt(); + int descriptorIndex = itr.nextU2toInt(); + int index = itr.nextU2toInt(); + LocalVariableItem item = new LocalVariableItem(startPc, length, nameIndex, descriptorIndex, index); + return item; + } + } + /* * getter setter */ public int getLocalVarTableLength() { return localVarTableLength; } + public void setLocalVarTableLength(int localVarTableLength) { this.localVarTableLength = localVarTableLength; } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java index 525d6a9071..01b80b0471 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/attr/StackMapTable.java @@ -2,9 +2,12 @@ public class StackMapTable extends AttributeInfo{ + private static String TYPE = STACK_MAP_TABLE; + @Override + public String getType() { + return TYPE; + } public StackMapTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); - // TODO Auto-generated constructor stub } - } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java index d29f77fb25..867e6eed5e 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coderising/jvm/method/Method.java @@ -63,7 +63,12 @@ public static Method parse(ConstantPool cp, ByteCodeIterator itr) { * @return */ public CodeAttr getCodeAttr() { - + for (int i = 0; i < attributeInfos.size(); i++) { + AttributeInfo attributeInfo = attributeInfos.get(i); + if(AttributeInfo.CODE.equals(attributeInfo.getType())){ + return (CodeAttr)attributeInfo; + } + } return null; } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java index 007362e95a..5cde9073f3 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/Stack.java @@ -31,4 +31,16 @@ public boolean isEmpty(){ public int size(){ return elementData.size(); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < size(); i++) { + sb.append(elementData.get(i)).append(", "); + } + sb.deleteCharAt(sb.length()-1); + sb.deleteCharAt(sb.length()-1); + sb.append("]"); + return sb.toString(); + } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java index e1bc00858f..1a29d59e48 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/StackUtil.java @@ -5,43 +5,143 @@ public class StackUtil { * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ + public static void reverse_useTwoStack(Stack s) { + if (s.size() < 2) { + return; + } + Stack stack1 = new Stack<>(); + Stack stack2 = new Stack<>(); + int length = s.size(); + for (int i = 0; i < length; i++) { + stack1.push(s.pop()); + } + for (int i = 0; i < length; i++) { + stack2.push(stack1.pop()); + } + for (int i = 0; i < length; i++) { + s.push(stack2.pop()); + } + } + public static void reverse(Stack s) { - + if (s.size() < 2) { + return; + } + Stack tmp = new Stack<>(); + int length = s.size(); + for (int i = 0; i < length; i++) { + tmp.push(s.pop()); + } + for (int i = 0; i < length; i++) { + addToBottom(s, tmp.pop()); + } } + /** * 添加元素到栈底部 + * * @param s * @param value */ - public static void addToBottom(Stack s, Integer value){ - + public static void addToBottom(Stack s, Integer value) { + /* + * Stack stack = new Stack<>(); for (int i = 0; i < s.size(); + * i++) { stack.push(s.pop()); } s.push(value); for (int i = 0; i < + * s.size(); i++) { s.push(stack.pop()); } + */ + if (s.isEmpty()) { + s.push(value); + } else { + Integer top = s.pop(); + addToBottom(s, value); + s.push(top); + } } + /** * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 * * @param o */ - public static void remove(Stack s,Object o) { - + public static boolean remove(Stack s, Object o) { + if (s.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + boolean flag = false; + Stack tmp = new Stack<>(); + while (!s.isEmpty()) { + tmp.push(s.pop()); + if (tmp.peek().equals(o)) { + flag = true; + + tmp.pop(); + for (int i = 0; i < tmp.size(); i++) { + s.push(tmp.pop()); + } + break; + } + } + return flag; } + /** - * 从栈顶取得len个元素, 原来的栈中元素保持不变 - * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * 从栈顶取得len个元素, 原来的栈中元素保持不变 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, + * 可以使用另外一个栈来辅助 + * * @param len * @return */ - public static Object[] getTop(Stack s,int len) { - return null; + public static Object[] getTop(Stack s, int len) { + Object[] result = new Object[len]; + Stack tmp = new Stack<>(); + for (int i = 0; i < len; i++) { + result[i] = s.peek(); + tmp.push(s.pop()); + } + for (int i = 0; i < len; i++) { + s.push(tmp.pop()); + } + return result; } + /** - * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz - * 使用堆栈检查字符串s中的括号是不是成对出现的。 - * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true - * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz 使用堆栈检查字符串s中的括号是不是成对出现的。 例如s = + * "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true 如果 s = "([b{x]y})", + * 则该字符串中的括号不是成对出现的, 该方法返回false; + * * @param s * @return */ - public static boolean isValidPairs(String s){ - return false; + public static boolean isValidPairs(String s) { + Stack stack = new Stack<>(); + char[] strCharArr = s.toCharArray(); + for (int i = 0; i < strCharArr.length; i++) { + char cc = strCharArr[i]; + int c = cc&0xffff; + if (isBracket(c)) { + if (c == 40 || c == 91 || c == 123) { + stack.push(c); + }else{ + int left = stack.pop(); + if(left+1!=c&&left+2!=c){ + return false; + } + } + } + } + return true; + } + + /** + * judge is Bracket or not + * @param c + * @return + */ + private static boolean isBracket(int c) { + if (c == 40 || c == 41 || c == 91 || c == 93 || c == 123 || c == 125) { + return true; + } else { + return false; + } } } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java index cd086dfe79..9f166de8d0 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java @@ -1,14 +1,52 @@ package com.coding.basic.stack.expr; +import java.util.Stack; + public class InfixExpr { String expr = null; + private Stack stack = new Stack<>(); public InfixExpr(String expr) { this.expr = expr; + init(); + } + public void init(){ + splitOpraAndNum(); + } + private void splitOpraAndNum() { + char[] array = expr.toCharArray(); + int mark = 0; + for (int i = 0; i < array.length; i++) { + char c = array[i]; + int cc = c&0xffff; + if(cc<48||cc>57){ + if((i-mark)>0){ + String num = expr.substring(mark, i); + stack.push(Integer.parseInt(num)); + } + }else{ + mark = i; + } + } + } + /** + * 转换成前序表达式进行计算 + * @return + */ + public float evaluatePre(){ + + return 0.0f; } + /** + * 循环扫描,每次找到最高优先级的操作符,如果是*或者/那么计算这个操作符两边的数字, + * 然后利用返回值改变以前的表达式,再次循环 + * 直到表达式变成只有一个数字的时候停止 + * @return + */ public float evaluate() { return 0.0f; } + } diff --git a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java index da5ab5f0a7..bcc79dc6d8 100644 --- a/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java +++ b/group17/82427129/JavaUtil/src/test/java/com/coderising/jvm/loader/ClassFileLoaderTest.java @@ -19,11 +19,12 @@ public class ClassFileLoaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path1 = "C:\\workPrograms\\GitRepo\\coding2017\\group17\\82427129\\JavaUtil\\target\\classes"; static String path2 = "D:\\workProgram\\GitRepo\\coding2017\\group17\\82427129\\JavaUtil\\target\\classes"; static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); loader.addClassPath(path2); String className = "com.coderising.jvm.test.EmployeeV1"; @@ -42,6 +43,7 @@ public void tearDown() throws Exception { public void testClassFileLength() { ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); loader.addClassPath(path2); String className = "com.coderising.jvm.test.EmployeeV1"; @@ -67,6 +69,7 @@ public void testGetClassPath() { @Test public void testMagicNumber(){ ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); loader.addClassPath(path2); String className = "com.coderising.jvm.test.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); From 3ee3ff1bba8effe0572bb362d9146125cb17c113 Mon Sep 17 00:00:00 2001 From: Ren650119726 <102228177@qq.com> Date: Sun, 16 Apr 2017 22:48:53 +0800 Subject: [PATCH 045/151] =?UTF-8?q?4-16=20jvm=E7=AC=AC=E4=B8=89=E6=AC=A1?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/attr/AttributeInfo.java | 19 ++ .../src/com/coderising/jvm/attr/CodeAttr.java | 116 ++++++++++ .../coderising/jvm/attr/LineNumberTable.java | 68 ++++++ .../jvm/attr/LocalVariableItem.java | 39 ++++ .../jvm/attr/LocalVariableTable.java | 58 +++++ .../coderising/jvm/attr/StackMapTable.java | 30 +++ .../com/coderising/jvm/clz/AccessFlag.java | 25 +++ .../src/com/coderising/jvm/clz/ClassFile.java | 92 ++++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 ++ .../coderising/jvm/constant/ClassInfo.java | 33 +++ .../coderising/jvm/constant/ConstantInfo.java | 38 ++++ .../coderising/jvm/constant/ConstantPool.java | 39 ++++ .../coderising/jvm/constant/FieldRefInfo.java | 54 +++++ .../jvm/constant/MethodRefInfo.java | 55 +++++ .../jvm/constant/NameAndTypeInfo.java | 45 ++++ .../jvm/constant/NullConstantInfo.java | 13 ++ .../coderising/jvm/constant/StringInfo.java | 26 +++ .../com/coderising/jvm/constant/UTF8Info.java | 32 +++ .../src/com/coderising/jvm/field/Field.java | 45 ++++ .../jvm/loader/ByteCodeIterator.java | 53 +++++ .../jvm/loader/ClassFileLoader.java | 137 ++++++++++++ .../jvm/loader/ClassFileParser.java | 143 ++++++++++++ .../src/com/coderising/jvm/method/Method.java | 91 ++++++++ .../jvm/test/ClassFileloaderTest.java | 203 ++++++++++++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 28 +++ .../src/com/coderising/jvm/util/Util.java | 24 +++ .../src/com/coding/basic/stack/ArrayList.java | 150 +++++++++++++ .../src/com/coding/basic/stack/InfixExpr.java | 18 ++ .../com/coding/basic/stack/InfixExprTest.java | 47 ++++ .../src/com/coding/basic/stack/Iterator.java | 8 + .../src/com/coding/basic/stack/List.java | 10 + .../src/com/coding/basic/stack/Stack.java | 48 +++++ .../src/com/coding/basic/stack/StackUtil.java | 66 ++++++ 33 files changed, 1872 insertions(+) create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/clz/AccessFlag.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassFile.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassIndex.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/ClassInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantPool.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/MethodRefInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/NullConstantInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/StringInfo.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/constant/UTF8Info.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/field/Field.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/loader/ClassFileLoader.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/method/Method.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/test/ClassFileloaderTest.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/test/EmployeeV1.java create mode 100644 group17/102228177/work4_16/src/com/coderising/jvm/util/Util.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/ArrayList.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/InfixExprTest.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/Iterator.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/List.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/Stack.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/StackUtil.java diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/attr/AttributeInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group17/102228177/work4_16/src/com/coderising/jvm/attr/CodeAttr.java b/group17/102228177/work4_16/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..a334a13d81 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,116 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.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.back(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/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableItem.java b/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableTable.java b/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..88f677b2c8 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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/group17/102228177/work4_16/src/com/coderising/jvm/attr/StackMapTable.java b/group17/102228177/work4_16/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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/group17/102228177/work4_16/src/com/coderising/jvm/clz/AccessFlag.java b/group17/102228177/work4_16/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassFile.java b/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4755266987 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassIndex.java b/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/ClassInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..af1e6bc65f --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.constant; + +/** + + * @Description 类常量信息 + + * @author REEFE + + * @time 2017年4月9日 + + */ +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..855b581f95 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,38 @@ +package com.coderising.jvm.constant; + +/** + + * @Description 常见常量项 + + * @author REEFE + + * @time 2017年4月9日 + + */ +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantPool.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..d4f91262b8 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + + +/** + + * @Description:常量池 + + * @author:REEFE + + * @time:2017年4月9日 + + */ +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/FieldRefInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/MethodRefInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/NullConstantInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/StringInfo.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/constant/UTF8Info.java b/group17/102228177/work4_16/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/field/Field.java b/group17/102228177/work4_16/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..7bc2656653 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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(); + + 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/group17/102228177/work4_16/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group17/102228177/work4_16/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..2eb83f3983 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,53 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/loader/ClassFileLoader.java b/group17/102228177/work4_16/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..81264ceed7 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,137 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + /*private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + }*/ + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + /*public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } +*/ + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + + +} diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/test/EmployeeV1.java b/group17/102228177/work4_16/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/util/Util.java b/group17/102228177/work4_16/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group17/102228177/work4_16/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i= maxLen){ + grow(); + } + elements[size] = o; + size++; + } + + /** + * 数组扩容 + */ + private void grow(){ + maxLen = maxLen + (maxLen >> 1); + Object[] newArr = new Object[maxLen]; + System.arraycopy(elements, 0, newArr, 0, size); + elements = newArr; + } + + /** + * 在指定索引处添加元素 + * @param i 指定索引 + * @param o 添加元素 + */ + public void add(int i,Object o){ + //判断插入位置大于数组实际长度 + if(i > size){ + size = i; + if(size >= maxLen){//数组大小大于数组最大容量则需要扩容 + grow(); + } + } + //插入位置不大于数组实际长度时,将插入位置的元素向后移。 + for (int j = size; j > i ; j++) { + elements[j] = elements[j-1]; + } + elements[i] = o; + size++; + } + + /** + * 获取传入索引的元素 + * @param index 索引 + * @return 返回传入索引的元素 + */ + public Object get(int index){ + //索引不在实际范围内 + if(index < 0||index >= size){ + throw new ArrayIndexOutOfBoundsException(); + } + for (int i = 0; i < size; i++) { + return elements[index]; + } + return null; + } + + /** + * 删除指定索引元素并返回 + * @param index + * @return 该索引处元素 + */ + public Object remove(int index){ + //索引不在实际范围内 + if(index < 0||index >= size){ + throw new ArrayIndexOutOfBoundsException(); + }else{ + for (int j = index; j < size-1; j++) { + elements[j]=elements[j+1]; + } + size--; + return elements[index]; + } + } + + /** + * 获取大小 + * @return + */ + public int size(){ + return size; + } + + public Iterator iterator(){ + return new ArrayListIterator(); + } + + private class ArrayListIterator implements Iterator{ + int cursor; + + @Override + public boolean hasNext() { + return cursor != size; + } + + @Override + public Object next() { + int i = cursor; + if(i >= size){ + throw new NoSuchElementException(); + } + if (i >= elements.length){ + throw new ConcurrentModificationException(); + } + cursor = i+1; + return elements[i]; + } + } + + public static void main(String[] args) { + ArrayList list = new ArrayList(); + list.add(0); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(6, 6); + list.remove(3); + for (int i = 0; i < list.size(); i++) { + System.out.println(i+":"+list.get(i)); + } + + Iterator it = list.iterator(); + while (it.hasNext()) { + System.out.println(it.next()); + } + } +} diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java new file mode 100644 index 0000000000..5c04740bfb --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java @@ -0,0 +1,18 @@ +package com.coding.basic.stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + return 0.0f; + } + + + + +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExprTest.java b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExprTest.java new file mode 100644 index 0000000000..7774cf98b0 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExprTest.java @@ -0,0 +1,47 @@ +package com.coding.basic.stack; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/Iterator.java b/group17/102228177/work4_16/src/com/coding/basic/stack/Iterator.java new file mode 100644 index 0000000000..f51a971a1c --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/Iterator.java @@ -0,0 +1,8 @@ +package com.coding.basic.stack; + +public interface Iterator { + + public boolean hasNext(); + public Object next(); + +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/List.java b/group17/102228177/work4_16/src/com/coding/basic/stack/List.java new file mode 100644 index 0000000000..2d2c693e0d --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/List.java @@ -0,0 +1,10 @@ +package com.coding.basic.stack; + +public interface List { + + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/Stack.java b/group17/102228177/work4_16/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..42b6362e2f --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack; + +import java.util.EmptyStackException; + +public class Stack { + private ArrayList elementData; + private int elementCount; + + public Stack() { + this.elementData = new ArrayList(); + this.elementCount = 0; + } + public void push(Object o){ + elementData.add(o); + elementCount++; + } + + public Object pop(){ + Object object = elementData.remove(elementCount-1); + elementCount--; + return object; + } + + public Object peek(){ + if(isEmpty()){ + throw new EmptyStackException(); + } + return elementData.get(elementCount-1); + } + public boolean isEmpty(){ + return elementCount==0; + } + public int size(){ + return elementCount; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < elementData.size(); i++) { + sb.append(elementData.get(i)).append(","); + } + sb = sb.deleteCharAt(sb.length()-1); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/StackUtil.java b/group17/102228177/work4_16/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..33fd75f6f1 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,66 @@ +package com.coding.basic.stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(!s.isEmpty()){ + Object last = getBottom(s,s.pop()); + reverse(s); + s.push(last); + } + } + + private static Object getBottom(Stack s,Object t){ + if(s.isEmpty()){ + return t; + } + Object last = getBottom(s, s.pop()); + s.push(t); + return last; + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + return null; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + return false; + } + + public static void main(String[] args) { + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + reverse(stack); + System.out.println(stack); + } + +} \ No newline at end of file From 5c9b6dd851f0ff7c1f221558bee08fc24b482c28 Mon Sep 17 00:00:00 2001 From: johnChnia Date: Mon, 17 Apr 2017 04:01:15 +0800 Subject: [PATCH 046/151] =?UTF-8?q?=E5=AE=8C=E6=88=90jvm=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E5=91=A8=E6=89=80=E6=9C=89=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/jvm/loader/ClassFileLoader.java | 57 +++++++++++++ .../src/main/java/jvm/loader/Directory.java | 81 ++++++++++++++++++ .../java/jvm/test/ClassFileloaderTest.java | 83 +++++++++++++++++++ .../src/main/java/jvm/test/EmployeeV1.java | 31 +++++++ 4 files changed, 252 insertions(+) create mode 100644 group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java create mode 100644 group24/315863321/src/main/java/jvm/loader/Directory.java create mode 100644 group24/315863321/src/main/java/jvm/test/ClassFileloaderTest.java create mode 100644 group24/315863321/src/main/java/jvm/test/EmployeeV1.java diff --git a/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java b/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..a300edafc7 --- /dev/null +++ b/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java @@ -0,0 +1,57 @@ +package jvm.loader; + + +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.List; + +import java.io.*; + +/** + * @// TODO: 2017/4/20 改成 try... with...resource + * @// TODO: 2017/4/20 close inputstream + * @// TODO: 2017/4/20 修改TreeInfo直接返回File + */ +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + for (int i = 0; i < clzPaths.size(); i++) { + // 找到指定类文件 + Directory.TreeInfo treeInfo = Directory.walk(clzPaths.get(i), className); + if (treeInfo.files.size() > 0) { + try { + FileInputStream fis = new FileInputStream(treeInfo.files.get(0)); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 自动增长 + byte[] buff = new byte[1024]; + int len; + while ((len = fis.read(buff)) != -1) { + bos.write(buff, 0, len); + } + return bos.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return null; + + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + public String getClassPath() { + StringBuilder sb = new StringBuilder(); + for (int index = 0; index < clzPaths.size(); index++) { + sb.append(clzPaths.get(index)); + sb.append(";"); + } + return sb.toString().substring(0, sb.length() - 1); + } + + +} diff --git a/group24/315863321/src/main/java/jvm/loader/Directory.java b/group24/315863321/src/main/java/jvm/loader/Directory.java new file mode 100644 index 0000000000..98f239434d --- /dev/null +++ b/group24/315863321/src/main/java/jvm/loader/Directory.java @@ -0,0 +1,81 @@ +package jvm.loader; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Created by john on 2017/4/17. + * + * @// TODO: 2017/4/20 实现 List.addAll(), list implements Iterable + */ +public final class Directory { + + public static File[] local(File dir, final String regex) { + return dir.listFiles(new FilenameFilter() { // 文件过滤接口 + private Pattern pattern = Pattern.compile(regex); + + @Override + public boolean accept(File dir, String name) { + return pattern.matcher(new File(name).getName()).matches(); + } + }); + } + + public static File[] local(String path, final String regex) { + return local(new File(path), regex); + } + + public static class TreeInfo implements Iterable { + public List files = new ArrayList<>(); + public List dirs = new ArrayList<>(); + + @Override + public Iterator iterator() { + return files.iterator(); + } + + public void addAll(TreeInfo other) { + files.addAll(other.files); + dirs.addAll(other.dirs); + } + + @Override + public String toString() { + return "dirs: " + dirs + + "\n\nfiles: " + files; + } + } + + public static TreeInfo walk(String start, String regex) { + return recuresDirs(new File(start), regex); + } + + public static TreeInfo walk(File start, String regex) { + return recuresDirs(start, regex); + } + + public static TreeInfo walk(File start) { + return recuresDirs(start, ".*");// 全部 + } + + public static TreeInfo walk(String start) { + return recuresDirs(new File(start), ".*");// 全部 + } + + public static TreeInfo recuresDirs(File startDir, String regex) { + TreeInfo result = new TreeInfo(); + for (File item : startDir.listFiles()) { + if (item.isDirectory()) { + result.dirs.add(item); + result.addAll(recuresDirs(item, regex)); + } else if (item.getName().matches(regex)) + result.files.add(item); + } + return result; + } + +} \ No newline at end of file diff --git a/group24/315863321/src/main/java/jvm/test/ClassFileloaderTest.java b/group24/315863321/src/main/java/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..70d400cb28 --- /dev/null +++ b/group24/315863321/src/main/java/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,83 @@ +package jvm.test; + +import jvm.loader.ClassFileLoader; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class ClassFileloaderTest { + + + static String path1 = "/Users/john/Documents/mygit/coding2017/group24/315863321/target/classes/jvm"; + static String path2 = "/Users/john/Documents"; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "EmployeeV1.class"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1026, byteCodes.length); + + } + + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "EmployeeV1.class"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + private String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } + +} diff --git a/group24/315863321/src/main/java/jvm/test/EmployeeV1.java b/group24/315863321/src/main/java/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..3fbdcef7bf --- /dev/null +++ b/group24/315863321/src/main/java/jvm/test/EmployeeV1.java @@ -0,0 +1,31 @@ +package jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age; + } + + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + + public static void main(String[] args) { + EmployeeV1 p = new EmployeeV1("Andy", 29); + p.sayHello(); + + } +} \ No newline at end of file From 3fc8b7880c23b0b8f626a1422c3915e4336abfc5 Mon Sep 17 00:00:00 2001 From: "kaitao.li" Date: Mon, 17 Apr 2017 09:32:17 +0800 Subject: [PATCH 047/151] =?UTF-8?q?jvm=E7=AC=AC=E4=B8=89=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A,=20=E5=9F=BA=E6=9C=AC=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/jvm/attr/AttributeInfo.java | 20 ++++++++ .../com/coding2017/jvm/attr/CodeAttr.java | 21 +++++++-- .../coding2017/jvm/attr/LineNumberTable.java | 3 +- .../jvm/attr/LocalVariableTable.java | 3 +- .../coding2017/jvm/attr/StackMapTable.java | 3 +- .../java/com/coding2017/jvm/field/Field.java | 46 +++++++++---------- .../jvm/loader/ClassFileParser.java | 10 ++++ .../com/coding2017/jvm/method/Method.java | 17 +++++++ 8 files changed, 94 insertions(+), 29 deletions(-) diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java index 2ec4931cac..d4678de264 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/AttributeInfo.java @@ -1,5 +1,8 @@ package com.coding2017.jvm.attr; +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.jvm.loader.ByteCodeIterator; + public abstract class AttributeInfo { public static final String CODE = "Code"; public static final String CONST_VALUE = "ConstantValue"; @@ -16,4 +19,21 @@ public AttributeInfo(int attrNameIndex, int attrLen) { this.attrLen = attrLen; } + public static AttributeInfo parse(ClassFile clzFile, ByteCodeIterator iter) { + int nameIndex = iter.nextU2ToInt(); + String name = clzFile.getConstantPool().getUTF8String(nameIndex); + int length = iter.nextU4ToInt(); + if (AttributeInfo.CODE.equals(name)) { + return CodeAttr.parse(clzFile, iter, nameIndex, length); + } else if (AttributeInfo.LINE_NUM_TABLE.equals(name)) { + return LineNumberTable.parse(clzFile, iter, nameIndex, length); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(name)) { + return LocalVariableTable.parse(clzFile, iter, nameIndex, length); + } else if (AttributeInfo.STACK_MAP_TABLE.equals(name)) { + return StackMapTable.parse(clzFile, iter, nameIndex, length); + } else { + throw new RuntimeException("not support attribute " + name); + } + } + } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java index a0a52ca70c..93bebc2dc7 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java @@ -39,9 +39,24 @@ public void setLocalVariableTable(LocalVariableTable t) { this.localVarTable = t; } - public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { - - return null; + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLength = iter.nextU4ToInt(); + String code = iter.nextUxToHexString(codeLength); + CodeAttr codeAttr = new CodeAttr(nameIndex, length, maxStack, maxLocals, codeLength, code); + int codeAttributeCount = iter.nextU2ToInt(); + for (int j = 0; j < codeAttributeCount; j++) { + AttributeInfo attributeInfo = AttributeInfo.parse(clzFile, iter); + if (attributeInfo instanceof LineNumberTable) { + codeAttr.setLineNumberTable((LineNumberTable) attributeInfo); + } else if (attributeInfo instanceof LocalVariableTable) { + codeAttr.setLocalVariableTable((LocalVariableTable) attributeInfo); + } else if (attributeInfo instanceof StackMapTable) { + codeAttr.setStackMapTable((StackMapTable) attributeInfo); + } + } + return codeAttr; } private void setStackMapTable(StackMapTable t) { diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java index 9449eafc1f..2878f874ed 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java @@ -1,5 +1,6 @@ package com.coding2017.jvm.attr; +import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.loader.ByteCodeIterator; import java.util.ArrayList; @@ -38,7 +39,7 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } - public static LineNumberTable parse(ByteCodeIterator iter) { + public static LineNumberTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { return null; } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java index 41dfb68e87..23dff851c8 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java @@ -1,5 +1,6 @@ package com.coding2017.jvm.attr; +import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.loader.ByteCodeIterator; import java.util.ArrayList; @@ -13,7 +14,7 @@ public LocalVariableTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - public static LocalVariableTable parse(ByteCodeIterator iter) { + public static LocalVariableTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { return null; } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java index a9fab7c2e8..653ecab830 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java @@ -1,5 +1,6 @@ package com.coding2017.jvm.attr; +import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.loader.ByteCodeIterator; public class StackMapTable extends AttributeInfo { @@ -10,7 +11,7 @@ public StackMapTable(int attrNameIndex, int attrLen) { super(attrNameIndex, attrLen); } - public static StackMapTable parse(ByteCodeIterator iter) { + public static StackMapTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { int index = iter.nextU2ToInt(); int len = iter.nextU4ToInt(); StackMapTable t = new StackMapTable(index, len); diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java index 3439d9c8bf..d521fca4e3 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java @@ -1,32 +1,32 @@ package com.coding2017.jvm.field; - import com.coding2017.jvm.constant.ConstantPool; import com.coding2017.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; - } + 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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ - - return null; - } + public static Field parse(ConstantPool pool, ByteCodeIterator iter) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attributeCount = iter.nextU2ToInt(); + if (attributeCount != 0) { + throw new RuntimeException("not parse field attribute"); + } + return new Field(accessFlag, nameIndex, descriptorIndex, pool); + } } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java index b684d1774d..87cf762ac4 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java @@ -4,6 +4,8 @@ import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.clz.ClassIndex; import com.coding2017.jvm.constant.*; +import com.coding2017.jvm.field.Field; +import com.coding2017.jvm.method.Method; public class ClassFileParser { @@ -32,6 +34,10 @@ public ClassFile parse(byte[] codes) { parseInterfaces(iterator); + Field.parse(classFile.getConstantPool(), iterator); + + Method.parse(classFile, iterator); + return classFile; } @@ -103,6 +109,10 @@ private void parseInterfaces(ByteCodeIterator iter) { System.out.println("interfaceCount:" + interfaceCount); + if (interfaceCount != 0) { + throw new RuntimeException("not parse interface"); + } + // TODO : 如果实现了interface, 这里需要解析 } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java index 9969d5dcf0..90ad8dec1e 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java @@ -1,5 +1,6 @@ package com.coding2017.jvm.method; +import com.coding2017.jvm.attr.AttributeInfo; import com.coding2017.jvm.attr.CodeAttr; import com.coding2017.jvm.clz.ClassFile; import com.coding2017.jvm.loader.ByteCodeIterator; @@ -42,7 +43,23 @@ public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIn } public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); + + method.parseAttributes(iter); return null; } + + private void parseAttributes(ByteCodeIterator iter) { + int methodAttributeCount = iter.nextU2ToInt(); + for (int i = 0; i < methodAttributeCount; i++) { + AttributeInfo attributeInfo = AttributeInfo.parse(this.clzFile, iter); + if (attributeInfo instanceof CodeAttr) { + this.setCodeAttr((CodeAttr) attributeInfo); + } + } + } } From db9ab4e74833bbc187dc7dcd970496f3395f0210 Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Mon, 17 Apr 2017 15:55:05 +0800 Subject: [PATCH 048/151] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=BA=A0=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coderising/jvm/attr/CodeAttr.java | 74 ++++++++++++++----- .../coderising/jvm/attr/LineNumberTable.java | 15 +++- .../jvm/attr/LocalVariableTable.java | 35 ++++++--- .../com/coderising/jvm/field/Field.java | 18 ++++- .../jvm/loader/ClassFileParser.java | 24 ++---- .../com/coderising/jvm/method/Method.java | 44 ++++++++--- 6 files changed, 149 insertions(+), 61 deletions(-) diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java index 63f4503244..b2779f1b70 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java @@ -3,30 +3,32 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.loader.ByteCodeIterator; -public class CodeAttr extends AttributeInfo{ - private int maxStack ; - private int maxLocals ; - private int codeLen ; +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 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) { @@ -34,16 +36,54 @@ public void setLineNumberTable(LineNumberTable t) { } public void setLocalVariableTable(LocalVariableTable t) { - this.localVarTable = t; + this.localVarTable = t; } - + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ - - - return null; + int attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Integer(); + int maxStack = iter.nextU2Int(); + int maxLocals = iter.nextU2Int(); + + int length = iter.nextU4Integer(); + String code = iter.nextUxToHexString(length); + + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, length, code); + + int exceptionTableLength = iter.nextU2Int(); + if (exceptionTableLength > 0) { + String exceptionTable = iter.nextUxToHexString(exceptionTableLength); + throw new RuntimeException("解析异常表异常:"+exceptionTable); + } + + int attributesCount = iter.nextU2Int(); + for (int i = 0; i < attributesCount; i++) { + int subAttributeNameIndex = iter.nextU2Int(); + iter.back(2); + + String subAttributeName = clzFile.getConstantPool().getUTF8String(subAttributeNameIndex); + + if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { + + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + + } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LOCAL_VAR_TABLE)) { + + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + + } else { + throw new RuntimeException("解析subAttribute异常-subAttributeName:"+subAttributeName); + } + + } + + return codeAttr; } + private void setStackMapTable(StackMapTable t) { this.stackMapTable = t; - + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java index 0e072f6d66..9c87155ca3 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java @@ -5,7 +5,7 @@ import com.coderising.jvm.loader.ByteCodeIterator; -public class LineNumberTable extends AttributeInfo{ +public class LineNumberTable extends AttributeInfo { List items = new ArrayList(); private static class LineNumberItem { @@ -39,8 +39,19 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } public static LineNumberTable parse(ByteCodeIterator iter) { + int attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Integer(); + LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex, attributeLength); + + int lineNumberTableLength = iter.nextU2Int(); + for (int i = 0; i < lineNumberTableLength; i++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.nextU2Int()); + lineNumberItem.setLineNum(iter.nextU2Int()); + lineNumberTable.addLineNumberItem(lineNumberItem); + } - return null; + return lineNumberTable; } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java index e69728e6aa..abbdae87d5 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java @@ -5,21 +5,36 @@ import com.coderising.jvm.loader.ByteCodeIterator; -public class LocalVariableTable extends AttributeInfo{ +public class LocalVariableTable extends AttributeInfo { List items = new ArrayList(); - + public LocalVariableTable(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); + super(attrNameIndex, attrLen); } - - public static LocalVariableTable parse(ByteCodeIterator iter){ - - return null; + + public static LocalVariableTable parse(ByteCodeIterator iter) { + int attributeNameIndex = iter.nextU2Int(); + int attributeLength = iter.nextU4Integer(); + + LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex, attributeLength); + + int localVariableTableLength = iter.nextU2Int(); + for (int i = 0; i < localVariableTableLength; i++) { + LocalVariableItem localVariableItem = new LocalVariableItem(); + localVariableItem.setStartPC(iter.nextU2Int()); + localVariableItem.setLength(iter.nextU2Int()); + localVariableItem.setNameIndex(iter.nextU2Int()); + localVariableItem.setDescIndex(iter.nextU2Int()); + localVariableItem.setIndex(iter.nextU2Int()); + localVariableTable.addLocalVariableItem(localVariableItem); + } + + return localVariableTable; } + private void addLocalVariableItem(LocalVariableItem item) { - this.items.add(item); + this.items.add(item); } - - + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java index 98fcbf5469..1d03d962e4 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/field/Field.java @@ -21,8 +21,22 @@ public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool po } public static Field parse(ConstantPool pool,ByteCodeIterator iter){ - - return null; + Field field = new Field(iter.nextU2Int(), iter.nextU2Int(), iter.nextU2Int(),pool); + int attributeCount=iter.nextU2Int(); + System.out.println("attributeCount:"+attributeCount); + for(int j=0;j fields = parseField(by,constant); - List methods = parseMethod(by,file); - file.setMinorVersion(minVersion); file.setMajorVersion(majorVersion); file.setAccessFlag(flag); file.setClassIndex(index); file.setConstPool(constant); + List fields = parseField(by,constant); + List methods = parseMethod(by,file); + + for(Field field:fields){ file.addField(field); } @@ -130,14 +131,7 @@ private List parseField(ByteCodeIterator by,ConstantPool pool) { List result = new ArrayList(); int fieldCount = by.nextU2Int(); for(int i=0;i parseMethod(ByteCodeIterator by,ClassFile file) { List result = new ArrayList(); int methodCount = by.nextU2Int(); for(int i=0;i Date: Mon, 17 Apr 2017 16:43:09 +0800 Subject: [PATCH 049/151] homework helper --- group24/Homework/1-FirstWeek/ArrayList.java | 35 ++ .../Homework/1-FirstWeek/BinaryTreeNode.java | 32 ++ group24/Homework/1-FirstWeek/Iterator.java | 7 + group24/Homework/1-FirstWeek/LinkedList.java | 125 +++++++ group24/Homework/1-FirstWeek/List.java | 9 + group24/Homework/1-FirstWeek/Queue.java | 61 +++ group24/Homework/1-FirstWeek/Stack.java | 24 ++ .../2-SecondWeek/litestruts/LoginAction.java | 39 ++ .../2-SecondWeek/litestruts/Struts.java | 34 ++ .../2-SecondWeek/litestruts/StrutsTest.java | 43 +++ .../2-SecondWeek/litestruts/View.java | 23 ++ group24/Homework/3-ThirdWeek/LinkedList.java | 125 +++++++ .../3-ThirdWeek/download/DownloadThread.java | 20 + .../3-ThirdWeek/download/FileDownloader.java | 73 ++++ .../download/FileDownloaderTest.java | 59 +++ .../3-ThirdWeek/download/api/Connection.java | 23 ++ .../download/api/ConnectionException.java | 5 + .../download/api/ConnectionManager.java | 10 + .../download/api/DownloadListener.java | 5 + .../download/impl/ConnectionImpl.java | 27 ++ .../download/impl/ConnectionManagerImpl.java | 15 + group24/Homework/4-FourWeek/LRUPageFrame.java | 57 +++ .../Homework/4-FourWeek/LRUPageFrameTest.java | 34 ++ .../jvm/loader/ClassFileLoader .java | 25 ++ .../jvm/test/ClassFileloaderTest.java | 92 +++++ .../4-FourWeek/jvm/test/EmployeeV1.java | 0 group24/Homework/5-FifthWeek/README.txt | 3 + group24/Homework/5-FifthWeek/StackUtil.java | 48 +++ .../Homework/5-FifthWeek/StackUtilTest.java | 65 ++++ .../5-FifthWeek/jvm/clz/AccessFlag.java | 23 ++ .../5-FifthWeek/jvm/clz/ClassFile .java | 58 +++ .../5-FifthWeek/jvm/clz/ClassIndex.java | 17 + .../5-FifthWeek/jvm/constant/ClassInfo.java | 28 ++ .../jvm/constant/ConstantInfo.java | 40 ++ .../jvm/constant/ConstantPool.java | 31 ++ .../jvm/constant/FieldRefInfo.java | 58 +++ .../jvm/constant/MethodRefInfo.java | 60 +++ .../jvm/constant/NameAndTypeInfo.java | 51 +++ .../jvm/constant/NullConstantInfo.java | 17 + .../5-FifthWeek/jvm/constant/StringInfo.java | 32 ++ .../5-FifthWeek/jvm/constant/UTF8Info.java | 37 ++ .../jvm/loader/ByteCodeIterator.java | 18 + .../jvm/loader/ClassFileLoader.java | 62 +++ .../jvm/loader/ClassFileParser.java | 62 +++ .../jvm/test/ClassFileloaderTest.java | 208 ++++++++++ .../5-FifthWeek/jvm/test/EmployeeV1.java | 28 ++ .../Homework/5-FifthWeek/jvm/util/Util.java | 24 ++ group24/Homework/6-SixWeek/InfixExpr.java | 15 + group24/Homework/6-SixWeek/InfixExprTest.java | 52 +++ group24/Homework/6-SixWeek/README.txt | 3 + .../6-SixWeek/jvm/attr/AttributeInfo.java | 19 + .../Homework/6-SixWeek/jvm/attr/CodeAttr.java | 70 ++++ .../6-SixWeek/jvm/attr/LineNumberTable.java | 55 +++ .../6-SixWeek/jvm/attr/LocalVariableItem.java | 39 ++ .../jvm/attr/LocalVariableTable.java | 42 +++ .../6-SixWeek/jvm/attr/StackMapTable.java | 30 ++ .../6-SixWeek/jvm/clz/AccessFlag.java | 25 ++ .../Homework/6-SixWeek/jvm/clz/ClassFile.java | 102 +++++ .../6-SixWeek/jvm/clz/ClassIndex.java | 19 + .../6-SixWeek/jvm/constant/ClassInfo.java | 28 ++ .../6-SixWeek/jvm/constant/ConstantInfo.java | 40 ++ .../6-SixWeek/jvm/constant/ConstantPool.java | 31 ++ .../6-SixWeek/jvm/constant/FieldRefInfo.java | 58 +++ .../6-SixWeek/jvm/constant/MethodRefInfo.java | 60 +++ .../jvm/constant/NameAndTypeInfo.java | 51 +++ .../jvm/constant/NullConstantInfo.java | 17 + .../6-SixWeek/jvm/constant/StringInfo.java | 32 ++ .../6-SixWeek/jvm/constant/UTF8Info.java | 37 ++ .../Homework/6-SixWeek/jvm/field/Field.java | 50 +++ .../jvm/loader/ByteCodeIterator.java | 57 +++ .../6-SixWeek/jvm/loader/ClassFileLoader.java | 140 +++++++ .../6-SixWeek/jvm/loader/ClassFileParser.java | 62 +++ .../Homework/6-SixWeek/jvm/method/Method.java | 80 ++++ .../jvm/test/ClassFileloaderTest.java | 282 ++++++++++++++ .../6-SixWeek/jvm/test/EmployeeV1.java | 28 ++ group24/Homework/6-SixWeek/jvm/util/Util.java | 24 ++ .../Homework/7-SevenWeek/InfixToPostfix.java | 14 + group24/Homework/7-SevenWeek/PostfixExpr.java | 18 + .../Homework/7-SevenWeek/PostfixExprTest.java | 41 ++ group24/Homework/7-SevenWeek/README.txt | 4 + .../7-SevenWeek/jvm/attr/AttributeInfo.java | 19 + .../7-SevenWeek/jvm/attr/CodeAttr.java | 70 ++++ .../7-SevenWeek/jvm/attr/LineNumberTable.java | 55 +++ .../jvm/attr/LocalVariableItem.java | 39 ++ .../jvm/attr/LocalVariableTable.java | 42 +++ .../7-SevenWeek/jvm/attr/StackMapTable.java | 30 ++ .../7-SevenWeek/jvm/clz/AccessFlag.java | 25 ++ .../7-SevenWeek/jvm/clz/ClassFile.java | 102 +++++ .../7-SevenWeek/jvm/clz/ClassIndex.java | 19 + .../7-SevenWeek/jvm/cmd/BiPushCmd.java | 23 ++ .../7-SevenWeek/jvm/cmd/ByteCodeCommand.java | 128 +++++++ .../7-SevenWeek/jvm/cmd/CommandParser.java | 85 +++++ .../7-SevenWeek/jvm/cmd/GetFieldCmd.java | 22 ++ .../jvm/cmd/GetStaticFieldCmd.java | 23 ++ .../7-SevenWeek/jvm/cmd/InvokeSpecialCmd.java | 23 ++ .../7-SevenWeek/jvm/cmd/InvokeVirtualCmd.java | 22 ++ .../Homework/7-SevenWeek/jvm/cmd/LdcCmd.java | 29 ++ .../7-SevenWeek/jvm/cmd/NewObjectCmd.java | 19 + .../7-SevenWeek/jvm/cmd/NoOperandCmd.java | 23 ++ .../7-SevenWeek/jvm/cmd/OneOperandCmd.java | 27 ++ .../7-SevenWeek/jvm/cmd/PutFieldCmd.java | 19 + .../7-SevenWeek/jvm/cmd/TwoOperandCmd.java | 67 ++++ .../7-SevenWeek/jvm/constant/ClassInfo.java | 28 ++ .../jvm/constant/ConstantInfo.java | 40 ++ .../jvm/constant/ConstantPool.java | 31 ++ .../jvm/constant/FieldRefInfo.java | 58 +++ .../jvm/constant/MethodRefInfo.java | 60 +++ .../jvm/constant/NameAndTypeInfo.java | 51 +++ .../jvm/constant/NullConstantInfo.java | 17 + .../7-SevenWeek/jvm/constant/StringInfo.java | 32 ++ .../7-SevenWeek/jvm/constant/UTF8Info.java | 37 ++ .../Homework/7-SevenWeek/jvm/field/Field.java | 50 +++ .../jvm/loader/ByteCodeIterator.java | 57 +++ .../jvm/loader/ClassFileLoader.java | 140 +++++++ .../jvm/loader/ClassFileParser.java | 62 +++ .../7-SevenWeek/jvm/method/Method.java | 80 ++++ .../jvm/print/ClassFilePrinter.java | 54 +++ .../jvm/print/ConstantPoolPrinter.java | 25 ++ .../jvm/test/ClassFileloaderTest.java | 354 ++++++++++++++++++ .../7-SevenWeek/jvm/test/EmployeeV1.java | 28 ++ .../Homework/7-SevenWeek/jvm/util/Util.java | 24 ++ 121 files changed, 5736 insertions(+) create mode 100644 group24/Homework/1-FirstWeek/ArrayList.java create mode 100644 group24/Homework/1-FirstWeek/BinaryTreeNode.java create mode 100644 group24/Homework/1-FirstWeek/Iterator.java create mode 100644 group24/Homework/1-FirstWeek/LinkedList.java create mode 100644 group24/Homework/1-FirstWeek/List.java create mode 100644 group24/Homework/1-FirstWeek/Queue.java create mode 100644 group24/Homework/1-FirstWeek/Stack.java create mode 100644 group24/Homework/2-SecondWeek/litestruts/LoginAction.java create mode 100644 group24/Homework/2-SecondWeek/litestruts/Struts.java create mode 100644 group24/Homework/2-SecondWeek/litestruts/StrutsTest.java create mode 100644 group24/Homework/2-SecondWeek/litestruts/View.java create mode 100644 group24/Homework/3-ThirdWeek/LinkedList.java create mode 100644 group24/Homework/3-ThirdWeek/download/DownloadThread.java create mode 100644 group24/Homework/3-ThirdWeek/download/FileDownloader.java create mode 100644 group24/Homework/3-ThirdWeek/download/FileDownloaderTest.java create mode 100644 group24/Homework/3-ThirdWeek/download/api/Connection.java create mode 100644 group24/Homework/3-ThirdWeek/download/api/ConnectionException.java create mode 100644 group24/Homework/3-ThirdWeek/download/api/ConnectionManager.java create mode 100644 group24/Homework/3-ThirdWeek/download/api/DownloadListener.java create mode 100644 group24/Homework/3-ThirdWeek/download/impl/ConnectionImpl.java create mode 100644 group24/Homework/3-ThirdWeek/download/impl/ConnectionManagerImpl.java create mode 100644 group24/Homework/4-FourWeek/LRUPageFrame.java create mode 100644 group24/Homework/4-FourWeek/LRUPageFrameTest.java create mode 100644 group24/Homework/4-FourWeek/jvm/loader/ClassFileLoader .java create mode 100644 group24/Homework/4-FourWeek/jvm/test/ClassFileloaderTest.java create mode 100644 group24/Homework/4-FourWeek/jvm/test/EmployeeV1.java create mode 100644 group24/Homework/5-FifthWeek/README.txt create mode 100644 group24/Homework/5-FifthWeek/StackUtil.java create mode 100644 group24/Homework/5-FifthWeek/StackUtilTest.java create mode 100644 group24/Homework/5-FifthWeek/jvm/clz/AccessFlag.java create mode 100644 group24/Homework/5-FifthWeek/jvm/clz/ClassFile .java create mode 100644 group24/Homework/5-FifthWeek/jvm/clz/ClassIndex.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/ClassInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/ConstantInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/ConstantPool.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/FieldRefInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/MethodRefInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/NameAndTypeInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/NullConstantInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/StringInfo.java create mode 100644 group24/Homework/5-FifthWeek/jvm/constant/UTF8Info.java create mode 100644 group24/Homework/5-FifthWeek/jvm/loader/ByteCodeIterator.java create mode 100644 group24/Homework/5-FifthWeek/jvm/loader/ClassFileLoader.java create mode 100644 group24/Homework/5-FifthWeek/jvm/loader/ClassFileParser.java create mode 100644 group24/Homework/5-FifthWeek/jvm/test/ClassFileloaderTest.java create mode 100644 group24/Homework/5-FifthWeek/jvm/test/EmployeeV1.java create mode 100644 group24/Homework/5-FifthWeek/jvm/util/Util.java create mode 100644 group24/Homework/6-SixWeek/InfixExpr.java create mode 100644 group24/Homework/6-SixWeek/InfixExprTest.java create mode 100644 group24/Homework/6-SixWeek/README.txt create mode 100644 group24/Homework/6-SixWeek/jvm/attr/AttributeInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/attr/CodeAttr.java create mode 100644 group24/Homework/6-SixWeek/jvm/attr/LineNumberTable.java create mode 100644 group24/Homework/6-SixWeek/jvm/attr/LocalVariableItem.java create mode 100644 group24/Homework/6-SixWeek/jvm/attr/LocalVariableTable.java create mode 100644 group24/Homework/6-SixWeek/jvm/attr/StackMapTable.java create mode 100644 group24/Homework/6-SixWeek/jvm/clz/AccessFlag.java create mode 100644 group24/Homework/6-SixWeek/jvm/clz/ClassFile.java create mode 100644 group24/Homework/6-SixWeek/jvm/clz/ClassIndex.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/ClassInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/ConstantInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/ConstantPool.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/FieldRefInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/MethodRefInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/NameAndTypeInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/NullConstantInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/StringInfo.java create mode 100644 group24/Homework/6-SixWeek/jvm/constant/UTF8Info.java create mode 100644 group24/Homework/6-SixWeek/jvm/field/Field.java create mode 100644 group24/Homework/6-SixWeek/jvm/loader/ByteCodeIterator.java create mode 100644 group24/Homework/6-SixWeek/jvm/loader/ClassFileLoader.java create mode 100644 group24/Homework/6-SixWeek/jvm/loader/ClassFileParser.java create mode 100644 group24/Homework/6-SixWeek/jvm/method/Method.java create mode 100644 group24/Homework/6-SixWeek/jvm/test/ClassFileloaderTest.java create mode 100644 group24/Homework/6-SixWeek/jvm/test/EmployeeV1.java create mode 100644 group24/Homework/6-SixWeek/jvm/util/Util.java create mode 100644 group24/Homework/7-SevenWeek/InfixToPostfix.java create mode 100644 group24/Homework/7-SevenWeek/PostfixExpr.java create mode 100644 group24/Homework/7-SevenWeek/PostfixExprTest.java create mode 100644 group24/Homework/7-SevenWeek/README.txt create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/AttributeInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/CodeAttr.java create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/LineNumberTable.java create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/LocalVariableItem.java create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/LocalVariableTable.java create mode 100644 group24/Homework/7-SevenWeek/jvm/attr/StackMapTable.java create mode 100644 group24/Homework/7-SevenWeek/jvm/clz/AccessFlag.java create mode 100644 group24/Homework/7-SevenWeek/jvm/clz/ClassFile.java create mode 100644 group24/Homework/7-SevenWeek/jvm/clz/ClassIndex.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/BiPushCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/ByteCodeCommand.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/CommandParser.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/GetFieldCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/LdcCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/NewObjectCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/NoOperandCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/OneOperandCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/PutFieldCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/cmd/TwoOperandCmd.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/ClassInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/ConstantInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/ConstantPool.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/FieldRefInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/MethodRefInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/NameAndTypeInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/NullConstantInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/StringInfo.java create mode 100644 group24/Homework/7-SevenWeek/jvm/constant/UTF8Info.java create mode 100644 group24/Homework/7-SevenWeek/jvm/field/Field.java create mode 100644 group24/Homework/7-SevenWeek/jvm/loader/ByteCodeIterator.java create mode 100644 group24/Homework/7-SevenWeek/jvm/loader/ClassFileLoader.java create mode 100644 group24/Homework/7-SevenWeek/jvm/loader/ClassFileParser.java create mode 100644 group24/Homework/7-SevenWeek/jvm/method/Method.java create mode 100644 group24/Homework/7-SevenWeek/jvm/print/ClassFilePrinter.java create mode 100644 group24/Homework/7-SevenWeek/jvm/print/ConstantPoolPrinter.java create mode 100644 group24/Homework/7-SevenWeek/jvm/test/ClassFileloaderTest.java create mode 100644 group24/Homework/7-SevenWeek/jvm/test/EmployeeV1.java create mode 100644 group24/Homework/7-SevenWeek/jvm/util/Util.java diff --git a/group24/Homework/1-FirstWeek/ArrayList.java b/group24/Homework/1-FirstWeek/ArrayList.java new file mode 100644 index 0000000000..4576c016af --- /dev/null +++ b/group24/Homework/1-FirstWeek/ArrayList.java @@ -0,0 +1,35 @@ +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + public void add(Object o){ + + } + public void add(int index, Object o){ + + } + + public Object get(int index){ + return null; + } + + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public Iterator iterator(){ + return null; + } + +} diff --git a/group24/Homework/1-FirstWeek/BinaryTreeNode.java b/group24/Homework/1-FirstWeek/BinaryTreeNode.java new file mode 100644 index 0000000000..d7ac820192 --- /dev/null +++ b/group24/Homework/1-FirstWeek/BinaryTreeNode.java @@ -0,0 +1,32 @@ +package com.coding.basic; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group24/Homework/1-FirstWeek/Iterator.java b/group24/Homework/1-FirstWeek/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/group24/Homework/1-FirstWeek/Iterator.java @@ -0,0 +1,7 @@ +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group24/Homework/1-FirstWeek/LinkedList.java b/group24/Homework/1-FirstWeek/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/group24/Homework/1-FirstWeek/LinkedList.java @@ -0,0 +1,125 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group24/Homework/1-FirstWeek/List.java b/group24/Homework/1-FirstWeek/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/group24/Homework/1-FirstWeek/List.java @@ -0,0 +1,9 @@ +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group24/Homework/1-FirstWeek/Queue.java b/group24/Homework/1-FirstWeek/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/group24/Homework/1-FirstWeek/Queue.java @@ -0,0 +1,61 @@ +package com.coding.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/group24/Homework/1-FirstWeek/Stack.java b/group24/Homework/1-FirstWeek/Stack.java new file mode 100644 index 0000000000..fedb243604 --- /dev/null +++ b/group24/Homework/1-FirstWeek/Stack.java @@ -0,0 +1,24 @@ +package com.coding.basic.stack; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + } + + public Object pop(){ + return null; + } + + public Object peek(){ + return null; + } + public boolean isEmpty(){ + return false; + } + public int size(){ + return -1; + } +} diff --git a/group24/Homework/2-SecondWeek/litestruts/LoginAction.java b/group24/Homework/2-SecondWeek/litestruts/LoginAction.java new file mode 100644 index 0000000000..dcdbe226ed --- /dev/null +++ b/group24/Homework/2-SecondWeek/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package com.coderising.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group24/Homework/2-SecondWeek/litestruts/Struts.java b/group24/Homework/2-SecondWeek/litestruts/Struts.java new file mode 100644 index 0000000000..85e2e22de3 --- /dev/null +++ b/group24/Homework/2-SecondWeek/litestruts/Struts.java @@ -0,0 +1,34 @@ +package com.coderising.litestruts; + +import java.util.Map; + + + +public class Struts { + + public static View runAction(String actionName, Map parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + return null; + } + +} diff --git a/group24/Homework/2-SecondWeek/litestruts/StrutsTest.java b/group24/Homework/2-SecondWeek/litestruts/StrutsTest.java new file mode 100644 index 0000000000..b8c81faf3c --- /dev/null +++ b/group24/Homework/2-SecondWeek/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group24/Homework/2-SecondWeek/litestruts/View.java b/group24/Homework/2-SecondWeek/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/group24/Homework/2-SecondWeek/litestruts/View.java @@ -0,0 +1,23 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group24/Homework/3-ThirdWeek/LinkedList.java b/group24/Homework/3-ThirdWeek/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/group24/Homework/3-ThirdWeek/LinkedList.java @@ -0,0 +1,125 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group24/Homework/3-ThirdWeek/download/DownloadThread.java b/group24/Homework/3-ThirdWeek/download/DownloadThread.java new file mode 100644 index 0000000000..900a3ad358 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/DownloadThread.java @@ -0,0 +1,20 @@ +package com.coderising.download; + +import com.coderising.download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + public DownloadThread( Connection conn, int startPos, int endPos){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + public void run(){ + + } +} diff --git a/group24/Homework/3-ThirdWeek/download/FileDownloader.java b/group24/Homework/3-ThirdWeek/download/FileDownloader.java new file mode 100644 index 0000000000..c3c8a3f27d --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/FileDownloader.java @@ -0,0 +1,73 @@ +package com.coderising.download; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + new DownloadThread(conn,0,length-1).start(); + + } catch (ConnectionException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group24/Homework/3-ThirdWeek/download/FileDownloaderTest.java b/group24/Homework/3-ThirdWeek/download/FileDownloaderTest.java new file mode 100644 index 0000000000..4ff7f46ae0 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/FileDownloaderTest.java @@ -0,0 +1,59 @@ +package com.coderising.download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "http://localhost:8080/test.jpg"; + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group24/Homework/3-ThirdWeek/download/api/Connection.java b/group24/Homework/3-ThirdWeek/download/api/Connection.java new file mode 100644 index 0000000000..0957eaf7f4 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group24/Homework/3-ThirdWeek/download/api/ConnectionException.java b/group24/Homework/3-ThirdWeek/download/api/ConnectionException.java new file mode 100644 index 0000000000..1551a80b3d --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group24/Homework/3-ThirdWeek/download/api/ConnectionManager.java b/group24/Homework/3-ThirdWeek/download/api/ConnectionManager.java new file mode 100644 index 0000000000..ce045393b1 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group24/Homework/3-ThirdWeek/download/api/DownloadListener.java b/group24/Homework/3-ThirdWeek/download/api/DownloadListener.java new file mode 100644 index 0000000000..bf9807b307 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group24/Homework/3-ThirdWeek/download/impl/ConnectionImpl.java b/group24/Homework/3-ThirdWeek/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..36a9d2ce15 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/impl/ConnectionImpl.java @@ -0,0 +1,27 @@ +package com.coderising.download.impl; + +import java.io.IOException; + +import com.coderising.download.api.Connection; + +public class ConnectionImpl implements Connection{ + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + return null; + } + + @Override + public int getContentLength() { + + return 0; + } + + @Override + public void close() { + + + } + +} diff --git a/group24/Homework/3-ThirdWeek/download/impl/ConnectionManagerImpl.java b/group24/Homework/3-ThirdWeek/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..172371dd55 --- /dev/null +++ b/group24/Homework/3-ThirdWeek/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,15 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + + return null; + } + +} diff --git a/group24/Homework/4-FourWeek/LRUPageFrame.java b/group24/Homework/4-FourWeek/LRUPageFrame.java new file mode 100644 index 0000000000..994a241a3d --- /dev/null +++ b/group24/Homework/4-FourWeek/LRUPageFrame.java @@ -0,0 +1,57 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + + } + + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + Node node = first; + while(node != null){ + buffer.append(node.pageNum); + + node = node.next; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } + + + +} diff --git a/group24/Homework/4-FourWeek/LRUPageFrameTest.java b/group24/Homework/4-FourWeek/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group24/Homework/4-FourWeek/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group24/Homework/4-FourWeek/jvm/loader/ClassFileLoader .java b/group24/Homework/4-FourWeek/jvm/loader/ClassFileLoader .java new file mode 100644 index 0000000000..55b4b70974 --- /dev/null +++ b/group24/Homework/4-FourWeek/jvm/loader/ClassFileLoader .java @@ -0,0 +1,25 @@ +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + return null; + } + + + public void addClassPath(String path) { + + } + + + + public String getClassPath(){ + + } + + + + + +} \ No newline at end of file diff --git a/group24/Homework/4-FourWeek/jvm/test/ClassFileloaderTest.java b/group24/Homework/4-FourWeek/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..77f1b93eb8 --- /dev/null +++ b/group24/Homework/4-FourWeek/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,92 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.loader.ClassFileLoader; + + + + + +public class ClassFileloaderTest { + + + static String path1 = "C:\\workspace\\min-jvm\\bin"; + static String path2 = "C:\temp"; + + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + int i=byteCodes.length; + // ע�⣺����ֽ������ܺ����JVM�汾�й�ϵ�� ����Կ�������õ��ൽ���ж�� + Assert.assertEquals(2048, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i s) { + + + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + return null; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + return false; + } + + +} diff --git a/group24/Homework/5-FifthWeek/StackUtilTest.java b/group24/Homework/5-FifthWeek/StackUtilTest.java new file mode 100644 index 0000000000..76f2cb7668 --- /dev/null +++ b/group24/Homework/5-FifthWeek/StackUtilTest.java @@ -0,0 +1,65 @@ +package com.coding.basic.stack; + +import java.util.Stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group24/Homework/5-FifthWeek/jvm/clz/AccessFlag.java b/group24/Homework/5-FifthWeek/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..2d93c5cebf --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/clz/AccessFlag.java @@ -0,0 +1,23 @@ +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/clz/ClassFile .java b/group24/Homework/5-FifthWeek/jvm/clz/ClassFile .java new file mode 100644 index 0000000000..0406ec7b46 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/clz/ClassFile .java @@ -0,0 +1,58 @@ +public class ClassFile { + + private int minorVersion; + private int majorVersion; + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + 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()); + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/clz/ClassIndex.java b/group24/Homework/5-FifthWeek/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..f1505a5050 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/clz/ClassIndex.java @@ -0,0 +1,17 @@ +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/constant/ClassInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/ConstantInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + 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); + + } +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/ConstantPool.java b/group24/Homework/5-FifthWeek/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } + + +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/FieldRefInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/MethodRefInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/NameAndTypeInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/NullConstantInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/StringInfo.java b/group24/Homework/5-FifthWeek/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + +} diff --git a/group24/Homework/5-FifthWeek/jvm/constant/UTF8Info.java b/group24/Homework/5-FifthWeek/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } + + + +} diff --git a/group24/Homework/5-FifthWeek/jvm/loader/ByteCodeIterator.java b/group24/Homework/5-FifthWeek/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..b3a25fa8c8 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + } + + + + +} diff --git a/group24/Homework/5-FifthWeek/jvm/loader/ClassFileLoader.java b/group24/Homework/5-FifthWeek/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..3b8ddb6a17 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/loader/ClassFileLoader.java @@ -0,0 +1,62 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + + return null; + } + +} \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/loader/ClassFileParser.java b/group24/Homework/5-FifthWeek/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..a29d9572cd --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/loader/ClassFileParser.java @@ -0,0 +1,62 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + + + + return null; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + return null; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + return null; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + return null; + } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { + + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + + + + } + +} diff --git a/group24/Homework/5-FifthWeek/jvm/test/ClassFileloaderTest.java b/group24/Homework/5-FifthWeek/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..657bf296f6 --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,208 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + + + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + + } + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + +} \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/test/EmployeeV1.java b/group24/Homework/5-FifthWeek/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group24/Homework/5-FifthWeek/jvm/util/Util.java b/group24/Homework/5-FifthWeek/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group24/Homework/5-FifthWeek/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + 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){ + + return null; + } + + 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/group24/Homework/6-SixWeek/jvm/attr/LocalVariableItem.java b/group24/Homework/6-SixWeek/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group24/Homework/6-SixWeek/jvm/attr/LocalVariableTable.java b/group24/Homework/6-SixWeek/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..14db5dca46 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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){ + + return null; + } + + + 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/group24/Homework/6-SixWeek/jvm/attr/StackMapTable.java b/group24/Homework/6-SixWeek/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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/group24/Homework/6-SixWeek/jvm/clz/AccessFlag.java b/group24/Homework/6-SixWeek/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group24/Homework/6-SixWeek/jvm/clz/ClassFile.java b/group24/Homework/6-SixWeek/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2a8dfb6123 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/clz/ClassFile.java @@ -0,0 +1,102 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + public String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + public String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group24/Homework/6-SixWeek/jvm/clz/ClassIndex.java b/group24/Homework/6-SixWeek/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group24/Homework/6-SixWeek/jvm/constant/ClassInfo.java b/group24/Homework/6-SixWeek/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/ConstantInfo.java b/group24/Homework/6-SixWeek/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + 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); + + } +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/ConstantPool.java b/group24/Homework/6-SixWeek/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } + + +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/FieldRefInfo.java b/group24/Homework/6-SixWeek/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/MethodRefInfo.java b/group24/Homework/6-SixWeek/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/NameAndTypeInfo.java b/group24/Homework/6-SixWeek/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/NullConstantInfo.java b/group24/Homework/6-SixWeek/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/StringInfo.java b/group24/Homework/6-SixWeek/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + +} diff --git a/group24/Homework/6-SixWeek/jvm/constant/UTF8Info.java b/group24/Homework/6-SixWeek/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } + + + +} diff --git a/group24/Homework/6-SixWeek/jvm/field/Field.java b/group24/Homework/6-SixWeek/jvm/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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/group24/Homework/6-SixWeek/jvm/loader/ByteCodeIterator.java b/group24/Homework/6-SixWeek/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group24/Homework/6-SixWeek/jvm/loader/ClassFileLoader.java b/group24/Homework/6-SixWeek/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + 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); + } + + + +} diff --git a/group24/Homework/6-SixWeek/jvm/test/EmployeeV1.java b/group24/Homework/6-SixWeek/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group24/Homework/6-SixWeek/jvm/util/Util.java b/group24/Homework/6-SixWeek/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group24/Homework/6-SixWeek/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i convert(String expr) { + + return null; + } + + + +} diff --git a/group24/Homework/7-SevenWeek/PostfixExpr.java b/group24/Homework/7-SevenWeek/PostfixExpr.java new file mode 100644 index 0000000000..dcbb18be4b --- /dev/null +++ b/group24/Homework/7-SevenWeek/PostfixExpr.java @@ -0,0 +1,18 @@ +package com.coding.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/group24/Homework/7-SevenWeek/PostfixExprTest.java b/group24/Homework/7-SevenWeek/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/group24/Homework/7-SevenWeek/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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/group24/Homework/7-SevenWeek/README.txt b/group24/Homework/7-SevenWeek/README.txt new file mode 100644 index 0000000000..6adfb7dc34 --- /dev/null +++ b/group24/Homework/7-SevenWeek/README.txt @@ -0,0 +1,4 @@ +1. ���ֽ���ָ��ת��Ϊjava ���� ����Ҫʵ�ֵ��ࣺ CommandParser.java ���� +2. ʵ�����Ƶ�javap �����Ҫʵ�ֵ��ࣺClassFilePrinter.java +3. ���ݽṹ�� ʵ��ǰ׺����ʽ����PrefixExpr.java �� ��׺����ʽ���� PostfixExpr.java +��׺����ʽת��׺����ʽ InfixToPostfix.java \ No newline at end of file diff --git a/group24/Homework/7-SevenWeek/jvm/attr/AttributeInfo.java b/group24/Homework/7-SevenWeek/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group24/Homework/7-SevenWeek/jvm/attr/CodeAttr.java b/group24/Homework/7-SevenWeek/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..c4c0c4c6c5 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/attr/CodeAttr.java @@ -0,0 +1,70 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.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){ + + return null; + } + + + 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){ + + return null; + } + + 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/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableItem.java b/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableTable.java b/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..14db5dca46 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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){ + + return null; + } + + + 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/group24/Homework/7-SevenWeek/jvm/attr/StackMapTable.java b/group24/Homework/7-SevenWeek/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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/group24/Homework/7-SevenWeek/jvm/clz/AccessFlag.java b/group24/Homework/7-SevenWeek/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group24/Homework/7-SevenWeek/jvm/clz/ClassFile.java b/group24/Homework/7-SevenWeek/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2a8dfb6123 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/clz/ClassFile.java @@ -0,0 +1,102 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + public String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + public String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/clz/ClassIndex.java b/group24/Homework/7-SevenWeek/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/BiPushCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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(); + } + + + +} diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/ByteCodeCommand.java b/group24/Homework/7-SevenWeek/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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); +} diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/CommandParser.java b/group24/Homework/7-SevenWeek/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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(); + } + + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/GetFieldCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/GetStaticFieldCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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); + } + +} diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/InvokeSpecialCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.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); + } + + + +} diff --git a/group24/Homework/7-SevenWeek/jvm/cmd/InvokeVirtualCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/LdcCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/NewObjectCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/NoOperandCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/OneOperandCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/PutFieldCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group24/Homework/7-SevenWeek/jvm/cmd/TwoOperandCmd.java b/group24/Homework/7-SevenWeek/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group24/Homework/7-SevenWeek/jvm/constant/ClassInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/ConstantInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + 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); + + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/ConstantPool.java b/group24/Homework/7-SevenWeek/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } + + +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/FieldRefInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/MethodRefInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/NameAndTypeInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/NullConstantInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/StringInfo.java b/group24/Homework/7-SevenWeek/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + +} diff --git a/group24/Homework/7-SevenWeek/jvm/constant/UTF8Info.java b/group24/Homework/7-SevenWeek/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } + + + +} diff --git a/group24/Homework/7-SevenWeek/jvm/field/Field.java b/group24/Homework/7-SevenWeek/jvm/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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/group24/Homework/7-SevenWeek/jvm/loader/ByteCodeIterator.java b/group24/Homework/7-SevenWeek/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group24/Homework/7-SevenWeek/jvm/loader/ClassFileLoader.java b/group24/Homework/7-SevenWeek/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + 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); + } + + @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/group24/Homework/7-SevenWeek/jvm/test/EmployeeV1.java b/group24/Homework/7-SevenWeek/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group24/Homework/7-SevenWeek/jvm/util/Util.java b/group24/Homework/7-SevenWeek/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group24/Homework/7-SevenWeek/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i Date: Mon, 17 Apr 2017 18:30:07 +0800 Subject: [PATCH 050/151] update infixExpr.java complete InfixExpression's evaluate --- .../coding/basic/stack/expr/InfixExpr.java | 120 +++++++++++++----- .../com/coding/basic/stack/expr/Token.java | 85 +++++++++++++ 2 files changed, 176 insertions(+), 29 deletions(-) create mode 100644 group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/Token.java diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java index 9f166de8d0..b498fc2758 100644 --- a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/InfixExpr.java @@ -1,52 +1,114 @@ package com.coding.basic.stack.expr; +import java.util.ArrayList; +import java.util.List; import java.util.Stack; +import com.coding.basic.stack.StackUtil; + public class InfixExpr { String expr = null; - private Stack stack = new Stack<>(); + private List tokenList = new ArrayList<>(); + private final static String regex = "-|\\+|\\*|/|\\(|\\)"; public InfixExpr(String expr) { this.expr = expr; init(); } - public void init(){ - splitOpraAndNum(); - } - private void splitOpraAndNum() { - char[] array = expr.toCharArray(); - int mark = 0; - for (int i = 0; i < array.length; i++) { - char c = array[i]; - int cc = c&0xffff; - if(cc<48||cc>57){ - if((i-mark)>0){ - String num = expr.substring(mark, i); - stack.push(Integer.parseInt(num)); - } - }else{ - mark = i; - } + + private void init() { + if (StackUtil.isValidPairs(expr)) { + initTokens(); + } else { + throw new RuntimeException( + "Syntax error, ( ) is not completed in your Expression"); } } + /** - * 转换成前序表达式进行计算 - * @return + * 表达式分解并入栈 */ - public float evaluatePre(){ - - return 0.0f; + private void initTokens() { + String[] nums = expr.split(regex); + ArrayList arrayList = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + if (!nums[i].equals("")) { + arrayList.add(nums[i]); + } + } + char[] exChars = expr.toCharArray(); + int numInx = 0; + for (int i = 0; i < exChars.length;) { + char ex = exChars[i]; + int item = ex & 0xffff; + if (item >= 48 && item <= 57) { + int numSize = arrayList.get(numInx++).length(); + String num = new String(exChars, i, numSize); + Token token = new Token(num, Token.NUMBER); + tokenList.add(token); + i += numSize; + } else { + Token token = new Token(String.valueOf(ex), Token.OPERA); + tokenList.add(token); + i += 1; + } + } } /** - * 循环扫描,每次找到最高优先级的操作符,如果是*或者/那么计算这个操作符两边的数字, - * 然后利用返回值改变以前的表达式,再次循环 - * 直到表达式变成只有一个数字的时候停止 + * 从左向右扫描所有token,当遇到同优先级或低优先级的操作符时,把之前的操作符依次出栈并计算结果 + * 扫描完所有token后,依次出栈所有操作数并计算结果 + * * @return */ public float evaluate() { - - return 0.0f; + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (int i = 0; i < tokenList.size(); i++) { + Token token = tokenList.get(i); + switch (token.getType()) { + case Token.NUMBER: + numStack.push(token.getNumValue()); + break; + case Token.OPERA: + if (opStack.isEmpty()) { + opStack.push(token); + } else { + while (!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())) { + Token preOper = opStack.pop(); + Float latter = numStack.pop(); + Float former = numStack.pop(); + Float result = caculate(preOper, latter, former); + numStack.push(result); + } + opStack.push(token); + } + break; + default: + throw new RuntimeException(" error not Number not Operate "); + } + } + while (!opStack.isEmpty()) { + Token pre = opStack.pop(); + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + Float result = caculate(pre, f1, f2); + numStack.push(result); + } + return numStack.pop(); + } + private Float caculate(Token t, Float latter,Float former){ + switch (t.getValue()) { + case "+": + return latter + former; + case "-": + return former - latter; + case "*": + return latter * former; + case "/": + return former / latter; + default: + throw new RuntimeException("operation"+t.getValue()+" isn't implemented"); + } } - } diff --git a/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/Token.java b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..bc6945c757 --- /dev/null +++ b/group17/82427129/JavaUtil/src/main/java/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,85 @@ +package com.coding.basic.stack.expr; + +import java.util.HashMap; + +/** + * 表达式中的数字或者操作符的抽象实体类 + * + * @author Walker + * + */ +public class Token { + private final static HashMap priority = new HashMap<>(4); + static { + priority.put("+", 1); + priority.put("-", 1); + priority.put("*", 2); + priority.put("/", 2); + } + private String value; + + public static final int NUMBER = 1; + public static final int OPERA = 2; + private int type; + + public Token(String v, int t) { + this.value = v; + this.type = t; + } + + public boolean isNum() { + return type == NUMBER; + } + + public boolean isOpera() { + return type == OPERA; + } + + @Override + public String toString() { + return value; + } + + public float getNumValue() { + return Float.parseFloat(value); + } + + public boolean hasLowerPriority(Token t) { + if (!this.isOpera() || !t.isOpera()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priority.get(this.value) - priority.get(t.value) < 0; + } + public boolean hasHigherPriority(Token t) { + if (!this.isOpera() || !t.isOpera()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priority.get(this.value) - priority.get(t.value) > 0; + } + public boolean hasEqualPriority(Token t) { + if (!this.isOpera() || !t.isOpera()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priority.get(this.value) - priority.get(t.value) == 0; + } + + /* + * getter setter + */ + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + +} From 7591001ff7e05091c843c82a86630443cb4c8114 Mon Sep 17 00:00:00 2001 From: zj <2258659044@qq.com> Date: Mon, 17 Apr 2017 19:36:45 +0800 Subject: [PATCH 051/151] coding --- .../coderising/jvm/attr/AttributeInfo.java | 76 +++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 94 ++++++ .../jvm/attr/ConstantValueAttr.java | 30 ++ .../coderising/jvm/attr/LineNumberTable.java | 60 ++++ .../jvm/attr/LocalVariableItem.java | 40 +++ .../jvm/attr/LocalVariableTable.java | 47 +++ .../coderising/jvm/attr/StackMapTable.java | 36 +++ .../com/coderising/jvm/clz/AccessFlag.java | 24 ++ .../src/com/coderising/jvm/clz/ClassFile.java | 92 ++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 ++ .../coderising/jvm/constant/ClassInfo.java | 24 ++ .../coderising/jvm/constant/ConstantInfo.java | 29 ++ .../coderising/jvm/constant/ConstantPool.java | 29 ++ .../coderising/jvm/constant/FieldRefInfo.java | 54 ++++ .../jvm/constant/MethodRefInfo.java | 55 ++++ .../jvm/constant/NameAndTypeInfo.java | 45 +++ .../jvm/constant/NullConstantInfo.java | 13 + .../coderising/jvm/constant/StringInfo.java | 26 ++ .../com/coderising/jvm/constant/UTF8Info.java | 30 ++ .../exception/AddAnotherParserException.java | 10 + .../exception/NoNextByteCodeException.java | 10 + .../jvm/exception/NotAClassFileException.java | 11 + .../src/com/coderising/jvm/field/Field.java | 65 +++++ .../jvm/loader/ByteCodeIterator.java | 113 ++++++++ .../jvm/loader/ClassFileLoader.java | 14 +- .../jvm/loader/ClassFileParser.java | 153 ++++++++++ .../src/com/coderising/jvm/method/Method.java | 66 +++++ .../Util.java} | 26 +- .../src/com/coding/basic/BinaryTree.java | 10 +- .../src/com/coding/basic/BinaryTreeNode.java | 74 ++--- .../src/com/coding/basic/Iterator.java | 16 +- .../zj-2017/src/com/coding/basic/List.java | 18 +- .../zj-2017/src/com/coding/basic/Queue.java | 8 +- .../zj-2017/src/com/coding/basic/Stack.java | 30 -- .../src/com/coding/basic/array/ArrayList.java | 37 ++- .../src/com/coding/basic/array/ArrayUtil.java | 10 +- .../com/coding/basic/linklist/LinkedList.java | 71 +++-- .../src/com/coding/basic/stack/Stack.java | 46 +++ .../src/com/coding/basic/stack/StackUtil.java | 158 ++++++++++ .../coding/basic/stack/expr/InfixExpr.java | 174 +++++++++++ .../com/coding/basic/stack/expr/Operator.java | 48 ++++ .../coderising/jvm/ClassFileloaderTest.java | 271 ++++++++++++++++++ .../jvm/{loader => }/EmployeeV1.java | 10 +- .../jvm/loader/ClassFileloaderTest.java | 87 ------ .../test/com/coding/basic/BinaryTreeTest.java | 117 ++++---- .../src/test/com/coding/basic/QueueTest.java | 128 ++++----- .../com/coding/basic/array/ArrayListTest.java | 4 +- .../com/coding/basic/array/ArrayUtilTest.java | 2 +- .../coding/basic/linklist/LinkedListTest.java | 14 +- .../coding/basic/{ => stack}/StackTest.java | 152 +++++----- .../com/coding/basic/stack/StackUtilTest.java | 95 ++++++ .../basic/stack/expr/InfixExprTest.java | 48 ++++ 52 files changed, 2468 insertions(+), 451 deletions(-) create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/ConstantValueAttr.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/clz/AccessFlag.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassIndex.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/exception/AddAnotherParserException.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NoNextByteCodeException.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NotAClassFileException.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/field/Field.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java rename group12/2258659044/zj-2017/src/com/coderising/jvm/{loader/ClassFileLoaderUtil.java => util/Util.java} (69%) delete mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/Stack.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/Stack.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/StackUtil.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java create mode 100644 group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java rename group12/2258659044/zj-2017/src/test/com/coderising/jvm/{loader => }/EmployeeV1.java (81%) delete mode 100644 group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/ClassFileloaderTest.java rename group12/2258659044/zj-2017/src/test/com/coding/basic/{ => stack}/StackTest.java (82%) create mode 100644 group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackUtilTest.java create mode 100644 group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/InfixExprTest.java diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/AttributeInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..a1369ab554 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,76 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.exception.AddAnotherParserException; +import com.coderising.jvm.loader.ByteCodeIterator; + +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; + } + + /** + * 解析属性 + * @param pool + * @param iter + * @return + */ + public static List parseAttributes(ConstantPool pool,ByteCodeIterator iter){ + + List attributeInfos = new ArrayList(); + try { + + int attrCount = iter.nextU2ToInt(); + for (int i = 0; i < attrCount; i++) { + + AttributeInfo attr = null; + String attrName = pool.getUTF8String(iter.nextU2ToInt()); + iter.back(ByteCodeIterator.numberTwo); + + switch (attrName) { + case AttributeInfo.CONST_VALUE: + attr = ConstantValueAttr.parse(iter); + break; + case AttributeInfo.CODE: + attr = CodeAttr.parse(pool,iter); + break; + case AttributeInfo.EXCEPTIONS: + //TODE + break; + case AttributeInfo.LINE_NUM_TABLE: + attr = LineNumberTable.parse(iter); + break; + case AttributeInfo.LOCAL_VAR_TABLE: + attr = LocalVariableTable.parse(iter); + break; + case AttributeInfo.STACK_MAP_TABLE: + attr = StackMapTable.parse(iter); + break; + default: + throw new AddAnotherParserException(); + } + attributeInfos.add(attr); + + } + } catch (AddAnotherParserException e) { + e.printStackTrace(); + } + return attributeInfos; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..3a2f0e6988 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,94 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + private List attributeInfos = new ArrayList<>(); + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code ) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + } + + + public static CodeAttr parse(ConstantPool pool,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); + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code); + + //解析exception_table start TODO + int exceptionTabLen = iter.nextU2ToInt(); + System.out.println("exception_table 的个数为"+exceptionTabLen); + //解析exception_table end TODO + + codeAttr.setAttributeInfos(AttributeInfo.parseAttributes(pool, iter)); + + return codeAttr; + } + + + public int getMaxStack() { + return maxStack; + } + + + public void setMaxStack(int maxStack) { + this.maxStack = maxStack; + } + + + public int getMaxLocals() { + return maxLocals; + } + + + public void setMaxLocals(int maxLocals) { + this.maxLocals = maxLocals; + } + + + public int getCodeLen() { + return codeLen; + } + + + public void setCodeLen(int codeLen) { + this.codeLen = codeLen; + } + + + public String getCode() { + return code; + } + + + public void setCode(String code) { + this.code = code; + } + + public List getAttributeInfos() { + return attributeInfos; + } + + + public void setAttributeInfos(List attributeInfos) { + this.attributeInfos = attributeInfos; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/ConstantValueAttr.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/ConstantValueAttr.java new file mode 100644 index 0000000000..697b484657 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/ConstantValueAttr.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class ConstantValueAttr extends AttributeInfo{ + + private int constantValueIndex; + + public int getConstantValueIndex() { + return constantValueIndex; + } + + public void setConstantValueIndex(int constantValueIndex) { + this.constantValueIndex = constantValueIndex; + } + + public ConstantValueAttr(int attrNameIndex, int attrLen,int constantValueIndex) { + super(attrNameIndex, attrLen); + this.constantValueIndex = constantValueIndex; + } + + public static ConstantValueAttr parse(ByteCodeIterator iter){ + + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int constantValueIndex = iter.nextU2ToInt(); + return new ConstantValueAttr(attrNameIndex,attrLen,constantValueIndex); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LineNumberTable.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..6029bf4253 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +@SuppressWarnings("unused") +public class LineNumberTable extends AttributeInfo { + + List 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 nameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(nameIndex,attrLen); + + int tableLen = iter.nextU2ToInt(); + + for (int i = 0; i < tableLen; i++) { + + int startPC = iter.nextU2ToInt(); + int lineNum = iter.nextU2ToInt(); + + LineNumberItem item = new LineNumberItem(); + item.setLineNum(startPC); + item.setLineNum(lineNum); + + lineNumberTable.addLineNumberItem(item); + } + + return lineNumberTable; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableItem.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..c7209a435e --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,40 @@ +package com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableTable.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..463b110458 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,47 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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 nameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(nameIndex,attrLen); + + int tableLen = iter.nextU2ToInt(); + + for (int i = 0; i < tableLen; i++) { + + int startPC = iter.nextU2ToInt(); + int len = iter.nextU2ToInt(); + int nameindex = iter.nextU2ToInt(); + int descrIndex = iter.nextU2ToInt(); + int index = iter.nextU2ToInt(); + + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(startPC); + item.setNameIndex(nameindex); + item.setLength(len); + item.setDescIndex(descrIndex); + item.setIndex(index); + localVariableTable.addLocalVariableItem(item); + } + return localVariableTable; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/StackMapTable.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..033b6bb179 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,36 @@ +package com.coderising.jvm.attr; + +import com.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 nameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + StackMapTable t = null; + t = new StackMapTable(nameIndex,attrLen); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.nextUxToHexString(attrLen); + t.setOriginalCode(code); + + return t; + } + + + private void setOriginalCode(String code) { + this.originalCode = code; + + } + + public String getOriginalCode() { + return originalCode; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/AccessFlag.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..5abd9961ac --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..c21a0988e5 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassIndex.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..7750d4439d --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e12b3e164e --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..c8035ae876 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..0e940b78d0 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ff9d5fb77 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..0feffa65b5 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..dcac7f97c4 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fa90d110fe --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d01065fd53 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..0aa9ee045b --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/AddAnotherParserException.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/AddAnotherParserException.java new file mode 100644 index 0000000000..9754f36adf --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/AddAnotherParserException.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.exception; + +public class AddAnotherParserException extends Exception{ + + private static final long serialVersionUID = 5171999484216739737L; + + public AddAnotherParserException(){ + super("you should add another parser to solve the unknown AttributeInfo or Constant!"); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NoNextByteCodeException.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NoNextByteCodeException.java new file mode 100644 index 0000000000..8819309841 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NoNextByteCodeException.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.exception; + +public class NoNextByteCodeException extends Exception{ + + private static final long serialVersionUID = -904433109427354744L; + + public NoNextByteCodeException(int byteNum){ + super("already haven't "+byteNum+" byte data!"); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NotAClassFileException.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NotAClassFileException.java new file mode 100644 index 0000000000..a627baf742 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/exception/NotAClassFileException.java @@ -0,0 +1,11 @@ +package com.coderising.jvm.exception; + +public class NotAClassFileException extends Exception{ + + private static final long serialVersionUID = -3645339333237670145L; + + public NotAClassFileException() { + super("this file not a java class file!"); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/field/Field.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..f29420615a --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,65 @@ +package com.coderising.jvm.field; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class Field { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private List attributeInfos = new ArrayList<>(); + + 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 int getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + + public List getAttributeInfos() { + return attributeInfos; + } + + public void setAttributeInfos(List attributeInfos) { + this.attributeInfos = attributeInfos; + } + + @Override + public String toString() { + + String fieldName = pool.getUTF8String(nameIndex); + String fieldDesc = pool.getUTF8String(descriptorIndex); + + return (fieldName+":"+fieldDesc); + } + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + + Field field = new Field(accessFlag,nameIndex,descriptorIndex,pool); + field.setAttributeInfos(AttributeInfo.parseAttributes(pool,iter)); + + return field; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..e69ae7b0b3 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,113 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.exception.NoNextByteCodeException; +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + + private byte[] codes; + private int cursor; + + public static int numberOne = 1; + public static int numberTwo = 2; + public static int numberFour = 4; + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + } + + public boolean hasNext(int len) { + return (cursor+len) <= codes.length; + } + + public byte[] next(int len){ + + byte[] data = new byte[len]; + + int j = 0; + for (int i = cursor; j < len; i++) { + data[j] = codes[i]; + j++; + } + cursor += len; + + return data; + } + + public int nextU2ToInt(){ + + if(!hasNext(numberTwo)){ + try { + throw new NoNextByteCodeException(numberTwo); + } catch (NoNextByteCodeException e) { + e.printStackTrace(); + } + } + return Util.byteToInt(next(numberTwo)); + } + + public int nextU4ToInt(){ + + if(!hasNext(numberFour)){ + try { + throw new NoNextByteCodeException(numberFour); + } catch (NoNextByteCodeException e) { + e.printStackTrace(); + } + } + return Util.byteToInt(next(numberFour)); + } + + public int nextInt(){ + + if(!hasNext(numberOne)){ + try { + throw new NoNextByteCodeException(numberOne); + } catch (NoNextByteCodeException e) { + e.printStackTrace(); + } + } + return Util.byteToInt(next(numberOne)); + } + + public String nextStr(int len){ + + if(!hasNext(len)){ + try { + throw new NoNextByteCodeException(len); + } catch (NoNextByteCodeException e) { + e.printStackTrace(); + } + } + char[] arr = new char[len]; + for (int i = 0; i < len; i++) { + arr[i] = (char)nextInt(); + } + return new String(arr); + } + + public String nextUxToHexString(int len) { + + if(!hasNext(len)){ + try { + throw new NoNextByteCodeException(len); + } catch (NoNextByteCodeException e) { + e.printStackTrace(); + } + } + return Util.byteToHexString(next(len)).toLowerCase(); + + } + + /** + * 回退 + */ + public void back(int backLen){ + + if( backLen<= this.cursor ){ + this.cursor -= backLen; + }else{ + this.cursor = 0; + } + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoader.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoader.java index 59d12540fc..4ba2613f1a 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -4,15 +4,19 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.exception.NotAClassFileException; +import com.coderising.jvm.util.Util; + public class ClassFileLoader { private List clzPaths = new ArrayList(); public byte[] readBinaryCode(String className) { - File clzFile = ClassFileLoaderUtil.getClzFile(clzPaths,className); + File clzFile = Util.getClzFile(clzPaths,className); - return ClassFileLoaderUtil.readClz(clzFile); + return Util.readClz(clzFile); } @@ -30,4 +34,10 @@ public String getClassPath(){ return buff.substring(0, buff.length()-1); } + public ClassFile loadClass(String className) throws NotAClassFileException { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..bd1fa61d5b --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,153 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.exception.AddAnotherParserException; +import com.coderising.jvm.exception.NotAClassFileException; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; +import com.coderising.jvm.util.Util; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) throws NotAClassFileException { + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + if(!validator(iterator)){ + throw new NotAClassFileException(); + } + ClassFile clazzFile = new ClassFile(); + + clazzFile.setMinorVersion(iterator.nextU2ToInt()); + + clazzFile.setMajorVersion(iterator.nextU2ToInt()); + + clazzFile.setConstPool(parseConstantPool(iterator)); + + clazzFile.setAccessFlag(parseAccessFlag(iterator)); + + clazzFile.setClassIndex(parseClassInfex(iterator)); + + parseInterfaces(iterator); + + //解析属性 + int fieldCount = iterator.nextU2ToInt(); + for (int i = 0; i < fieldCount; i++) { + clazzFile.addField(Field.parse(clazzFile.getConstantPool(), iterator)); + } + //解析方法 + int methodCount = iterator.nextU2ToInt(); + for (int i = 0; i < methodCount; i++) { + clazzFile.addMethod(Method.parse(clazzFile.getConstantPool(), iterator));; + } + + return clazzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter){ + + return new AccessFlag(iter.nextU2ToInt()); + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter){ + + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextU2ToInt()); + classIndex.setSuperClassIndex(iter.nextU2ToInt()); + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter){ + + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + + try { + + int poolSize = iter.nextU2ToInt(); + for (int i = 1; i < poolSize; i++) { + int tag = iter.nextInt(); + switch (tag) { + case ConstantInfo.UTF8_INFO: + UTF8Info UTF8Info = new UTF8Info(pool); + int len = iter.nextU2ToInt(); + String value = iter.nextStr(len); + UTF8Info.setLength(len); + UTF8Info.setValue(value); + pool.addConstantInfo(UTF8Info); + break; + case ConstantInfo.FLOAT_INFO: + //TODO + break; + case ConstantInfo.CLASS_INFO: + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.nextU2ToInt()); + pool.addConstantInfo(classInfo); + break; + case ConstantInfo.STRING_INFO: + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(stringInfo); + break; + case ConstantInfo.FIELD_INFO: + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(fieldRefInfo); + break; + case ConstantInfo.METHOD_INFO: + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(methodRefInfo); + break; + case ConstantInfo.NAME_AND_TYPE_INFO: + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameAndTypeInfo); + break; + default: + throw new AddAnotherParserException(); + } + } + } catch (AddAnotherParserException e) { + e.printStackTrace(); + } + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter){ + + int interfaceCount = iter.nextU2ToInt(); + System.out.println("接口数量为:"+interfaceCount); + // TODO + } + + /** + * 校验是否为class文件 + * @param iterator + * @return + */ + private boolean validator(ByteCodeIterator iterator){ + + if(iterator.hasNext(4)){ + byte[] magicByte = iterator.next(4); + String magicNumber = Util.byteToHexString(magicByte); + if("cafebabe".equals(magicNumber)){ + return true; + } + } + return false; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..c8d8065df8 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,66 @@ +package com.coderising.jvm.method; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private ConstantPool pool; + private List attributeInfos = new ArrayList<>(); + + + public Method(ConstantPool pool,int accessFlag, int nameIndex, int descriptorIndex) { + this.pool = pool; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + public static Method parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + + Method method = new Method(pool,accessFlag,nameIndex,descriptorIndex); + method.setAttributeInfos(AttributeInfo.parseAttributes(pool,iter)); + + return method; + } + + + public int getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + + public ConstantPool getPool() { + return pool; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + + public List getAttributeInfos() { + return attributeInfos; + } + + public void setAttributeInfos(List attributeInfos) { + this.attributeInfos = attributeInfos; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoaderUtil.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/util/Util.java similarity index 69% rename from group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoaderUtil.java rename to group12/2258659044/zj-2017/src/com/coderising/jvm/util/Util.java index 61faafb77d..d0456fead2 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileLoaderUtil.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/util/Util.java @@ -1,4 +1,4 @@ -package com.coderising.jvm.loader; +package com.coderising.jvm.util; import java.io.ByteArrayOutputStream; import java.io.File; @@ -7,8 +7,27 @@ import java.io.InputStream; import java.util.List; -public class ClassFileLoaderUtil { - +public class Util { + + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i root; @SuppressWarnings({ "rawtypes", "unchecked" }) public > BinaryTreeNode insert(T o){ @@ -44,12 +44,12 @@ public > BinaryTreeNode insert(T o){ * @param node * @return */ - public List traversalBefore(BinaryTreeNode node){ + public List traversalBefore(BinaryTreeNode node){ //所有数据集合 - List datas = new ArrayList(); + List datas = new ArrayList<>(); return traversal(node,datas); } - private List traversal(BinaryTreeNode node,List datas){ + private List traversal(BinaryTreeNode node,List datas){ if(node !=null){ datas.add(node.getData()); @@ -59,7 +59,7 @@ private List traversal(BinaryTreeNode node,List datas){ return datas; } - public BinaryTreeNode getRoot() { + public BinaryTreeNode getRoot() { return root; } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTreeNode.java b/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTreeNode.java index a8e6b66edd..5e8c90fa54 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTreeNode.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTreeNode.java @@ -1,37 +1,37 @@ -package com.coding.basic; -public class BinaryTreeNode { - - private Object data; - //父节点 - private BinaryTreeNode parent; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public Object getData() { - return data; - } - public void setData(Object data) { - this.data = data; - } - - public BinaryTreeNode getLeft() { - return left; - } - public void setLeft(BinaryTreeNode left) { - this.left = left; - } - - public BinaryTreeNode getRight() { - return right; - } - public void setRight(BinaryTreeNode right) { - this.right = right; - } - - public BinaryTreeNode getParent() { - return parent; - } - public void setParent(BinaryTreeNode parent) { - this.parent = parent; - } -} +package com.coding.basic; +public class BinaryTreeNode { + + private E data; + //父节点 + private BinaryTreeNode parent; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public E getData() { + return data; + } + public void setData(E data) { + this.data = data; + } + + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode getParent() { + return parent; + } + public void setParent(BinaryTreeNode parent) { + this.parent = parent; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/Iterator.java b/group12/2258659044/zj-2017/src/com/coding/basic/Iterator.java index c854120212..d72c308c07 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/Iterator.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/Iterator.java @@ -1,8 +1,8 @@ -package com.coding.basic; - -public interface Iterator { - - public boolean hasNext(); - public Object next(); - -} +package com.coding.basic; + +public interface Iterator { + + public boolean hasNext(); + public Object next(); + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/List.java b/group12/2258659044/zj-2017/src/com/coding/basic/List.java index a5a3688eb6..7fd5915bae 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/List.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/List.java @@ -1,10 +1,10 @@ -package com.coding.basic; - -public interface List { - - public void add(Object o); - public void add(int index, Object o); - public Object get(int index); - public Object remove(int index); - public int size(); +package com.coding.basic; + +public interface List { + + public void add(E o); + public void add(int index, E o); + public E get(int index); + public E remove(int index); + public int size(); } \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java b/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java index aa8429ac59..169fc0dcb9 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java @@ -2,16 +2,16 @@ import com.coding.basic.linklist.LinkedList; -public class Queue { +public class Queue { - private LinkedList element = new LinkedList(); + private LinkedList element = new LinkedList(); - public void enQueue(Object o){ + public void enQueue(E o){ element.add(o); } - public Object deQueue(){ + public E deQueue(){ return element.removeFirst(); } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/Stack.java b/group12/2258659044/zj-2017/src/com/coding/basic/Stack.java deleted file mode 100644 index 2b08e856c1..0000000000 --- a/group12/2258659044/zj-2017/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.array.ArrayList; - -public class Stack { - - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - - elementData.add(o); - } - - public Object pop(){ - - return elementData.remove(size()-1); - } - - public Object peek(){ - - return elementData.get(size()-1); - } - public boolean isEmpty(){ - - return size()==0; - } - public int size(){ - return elementData.size(); - } -} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java index 4bbf60adf9..73f3b9649e 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java @@ -5,7 +5,7 @@ import com.coding.basic.Iterator; import com.coding.basic.List; -public class ArrayList implements List { +public class ArrayList implements List { private int size = 0; /*扩容因子*/ @@ -15,12 +15,12 @@ public class ArrayList implements List { /*扩容引用*/ private Object[] newElementData; - public void add(Object o){ + public void add(E o){ grow(); elementData[size] = o; size ++; } - public void add(int index, Object o){ + public void add(int index, E o){ if(index<0||index>size){ throw new IndexOutOfBoundsException("Index: "+index+",Size:"+size); @@ -36,19 +36,21 @@ public void add(int index, Object o){ size ++; } - public Object get(int index){ + public E get(int index){ - if(index<0||index>size){ - throw new IndexOutOfBoundsException("Index: "+index+",Size:"+size); - } - return elementData[index]; + rangeCheck(index); + return elementData(index); } - public Object remove(int index){ + public E remove(int index){ - Object o = elementData[index]; - System.arraycopy(elementData, index+1, elementData, index, size-(index+1)); - size --; + rangeCheck(index); + E o = elementData(index); + int i = this.size - index - 1; + if (i > 0) { + System.arraycopy(this.elementData, index + 1, this.elementData, index, i); + } + this.elementData[(--this.size)] = null; return o; } @@ -74,6 +76,17 @@ private void grow(){ } } + private void rangeCheck(int index) { + + if (index >= this.size) { + throw new IndexOutOfBoundsException("Index: "+index+",Size:"+size); + } + } + + @SuppressWarnings("unchecked") + E elementData(int index) { + return (E) elementData[index]; + } public Iterator iterator(){ diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayUtil.java b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayUtil.java index de11fdbca5..0bd2cef66b 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayUtil.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayUtil.java @@ -112,7 +112,7 @@ public int[] merge2(int[] array1, int[] array2){ bitmap[array2[i]]=true; } - ArrayList ls = new ArrayList(); + ArrayList ls = new ArrayList<>(); for (int i = 0; i < bitmap.length; i++) { if(bitmap[i]==true){ ls.add(i); @@ -149,7 +149,7 @@ public int[] fibonacci(int max){ int[] array = {}; if(max <= 1)return array; //生成 斐波那契数列的ArrayList集合 - ArrayList ls = new ArrayList(); + ArrayList ls = new ArrayList<>(); ls.add(1);ls.add(1); int next;int i = 1; while(true){ @@ -171,7 +171,7 @@ public int[] fibonacci(int max){ */ public int[] getPrimes(int max){ - ArrayList primesList = new ArrayList(); + ArrayList primesList = new ArrayList<>(); boolean flag; for (int i = 2; i < max; i++) { flag = false; @@ -197,7 +197,7 @@ public int[] getPrimes(int max){ public int[] getPerfectNumbers(int max){ int temp; - ArrayList perfectList = new ArrayList(); + ArrayList perfectList = new ArrayList(); for (int i = 6; i <= max; i++) { temp = 0; for (int j = 1; j <= (i/2); j++) { @@ -234,7 +234,7 @@ public String join(int[] array, String seperator){ * @param ls * @return */ - public int[] objList2int(ArrayList ls){ + public int[] objList2int(ArrayList ls){ Object[] objArr = ls.toArray(); int[] array = new int[ls.size()]; diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/linklist/LinkedList.java b/group12/2258659044/zj-2017/src/com/coding/basic/linklist/LinkedList.java index 0132efaa00..5ee8881fa0 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/linklist/LinkedList.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/linklist/LinkedList.java @@ -4,57 +4,57 @@ import com.coding.basic.Iterator; import com.coding.basic.List; -import com.coding.basic.Stack; +import com.coding.basic.stack.Stack; -public class LinkedList implements List { +public class LinkedList implements List { - private Node head; + private Node head; private int size = 0; - public void add(Object o){ + public void add(E o){ - Node addNode = new Node(); + Node addNode = new Node<>(); addNode.data = o; if(size==0){ head = addNode; }else{ //获取最后一个节点 - Node lastNode = getPointNode(size-1); + Node lastNode = getPointNode(size-1); lastNode.next = addNode; } size++; } - public void add(int index , Object o){ + public void add(int index , E o){ - Node addNode = new Node(); + Node addNode = new Node<>(); addNode.data = o; if(index == 0){ //添加头结点 addFirst(o); }else if(index == size){//添加尾节点 addLast(o); }else{//在投节点与尾部添加节点 - Node prePointNode = getPointNode(index-1); - Node pointNode = prePointNode.next; + Node prePointNode = getPointNode(index-1); + Node pointNode = prePointNode.next; prePointNode.next = addNode; addNode.next = pointNode; size ++; } } - public Object get(int index){ + public E get(int index){ - Node node = getPointNode(index); + Node node = getPointNode(index); return node.data; } - public Object remove(int index){ + public E remove(int index){ - Node pointNode = getPointNode(index); - Node nextPointNode = pointNode.next; + Node pointNode = getPointNode(index); + Node nextPointNode = pointNode.next; if(index ==0){ head = nextPointNode; }else{ - Node prePointNode = getPointNode(index-1); + Node prePointNode = getPointNode(index-1); prePointNode.next = nextPointNode; } size --; @@ -65,10 +65,10 @@ public int size(){ return size; } - public void addFirst(Object o){ + public void addFirst(E o){ - Node secondNode = head; - head = new Node(); + Node secondNode = head; + head = new Node<>(); head.data = o; if(size>0){ head.next = secondNode; @@ -76,16 +76,16 @@ public void addFirst(Object o){ size ++; } - public void addLast(Object o){ + public void addLast(E o){ add(o); } - public Object removeFirst(){ + public E removeFirst(){ return remove(0); } - public Object removeLast(){ + public E removeLast(){ return remove(size-1); } @@ -118,21 +118,21 @@ public Object next() { * 获取指定的节点 * @return */ - private Node getPointNode(int index){ + private Node getPointNode(int index){ if(index<0||index>size){ throw new IndexOutOfBoundsException("Index: "+index+",Size:"+size+""); } - Node node = head; + Node node = head; for (int i = 0; i < index; i++) { node = node.next; } return node; } - private static class Node{ - Object data; - Node next; + private static class Node{ + E data; + Node next; } @@ -142,8 +142,8 @@ private static class Node{ */ public void reverse(){ - Stack stack = new Stack(); - Node node; + Stack stack = new Stack(); + Node node; //缓存原链表数据 for (node = head; node!=null;node = node.next) { stack.push(node.data); @@ -198,10 +198,10 @@ public void remove(int i, int length){ * 返回的结果应该是[101,301,401,601] * @param list */ - public int[] getElements(LinkedList list){ + public int[] getElements(LinkedList list){ int[] array = new int[list.size()]; for (int i = 0; i < array.length; i++) { - array[i] = (int) get((int)list.get(i)); + array[i] = (int) get(list.get(i)); } return array; } @@ -212,12 +212,11 @@ public int[] getElements(LinkedList list){ * @param list */ - public void subtract(LinkedList list){ + public void subtract(LinkedList list){ for (int i = 0; i < size; i++) { for (int j = 0; j < list.size(); j++) { if(get(i).equals(list.get(j))){ remove(i); - i--; } } } @@ -259,13 +258,13 @@ public void removeRange(int min, int max){ * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 * @param list */ - public LinkedList intersection( LinkedList list){ + public LinkedList intersection( LinkedList list){ - LinkedList newList = new LinkedList(); + LinkedList newList = new LinkedList<>(); for (int i = 0; i < size; i++) { for (int j = 0; j < list.size(); j++) { if(get(i).equals(list.get(j))){ - newList.add(get(i)); + newList.add((E)get(i)); } } } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/Stack.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..f1ede1f8ab --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,46 @@ +package com.coding.basic.stack; + +import com.coding.basic.array.ArrayList; + +public class Stack { + + private ArrayList elementData = new ArrayList(); + + public void push(E o){ + + elementData.add(o); + } + + public E pop(){ + + return elementData.remove(size()-1); + } + + public E peek(){ + + return elementData.get(size()-1); + } + public boolean isEmpty(){ + + return size()==0; + } + public int size(){ + return elementData.size(); + } + + @Override + public String toString() { + + StringBuffer sBuffer = new StringBuffer(); + sBuffer.append("["); + + for (int i = size()-1; i >= 0; i--) { + if(i == 0){ + sBuffer.append(elementData.get(i)+"]"); + }else{ + sBuffer.append(elementData.get(i)+","); + } + } + return sBuffer.toString(); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackUtil.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..871b2fce69 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,158 @@ +package com.coding.basic.stack; + +import java.util.HashMap; +import java.util.Map; + +public class StackUtil { + + private static Map markMap; + + static { + //初始化括号对 + markMap = new HashMap(); + markMap.put('(', ')'); + markMap.put('[', ']'); + markMap.put('{', '}'); + } + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param + */ + public static void reverse(Stack s) { + + if(s == null||s.isEmpty()){ + return; + } + E last = getBottom(s,s.pop()); + reverse(s); + s.push(last); + } + + /** + * 获取栈底部数据 + * @param + * @param s + * @return + */ + private static E getBottom(Stack s,E val){ + + if(s.isEmpty()){ + return val; + } + E lst = getBottom(s,s.pop()); + s.push(val); + return lst; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param + * + * @param o + */ + public static void remove(Stack s,E o) { + + if(s == null||s.isEmpty()){ + return; + } + E res = s.pop(); + if(res.equals(o)){ + return; + } + remove(s,o); + s.push(res); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param + * @param len + * @return + */ + + public static Object[] getTop(Stack s,int len) { + + if(s == null||s.isEmpty()||len <= 0){ + return null; + } + + //当len的长度大于栈s的长度时返回栈s全部数据 + int size = s.size()>=len? len:s.size(); + + Object[] objs = new Object[size]; + + putValueToArray(s,objs,0); + + return objs; + } + + /** + * 将获取的元素放到数组中 + * @param + * @param s + * @param objs + * @param count + */ + public static void putValueToArray(Stack s,Object[] objs,int count){ + + E res = s.pop(); + count++; + objs[count-1] = res; + if(count== objs.length){ + s.push(res); + return; + } + putValueToArray(s,objs,count); + s.push(res); + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + + if(!validation(s)){ + return false; + } + Stack markStack = new Stack<>(); + char[] charArr = s.toCharArray(); + for (int i = 0; i < charArr.length; i++) { + if(markMap.containsKey(charArr[i])){ + markStack.push(charArr[i]); + } + if(markMap.containsValue(charArr[i])){ + if(markMap.get(markStack.pop()).equals(charArr[i])){ + continue; + }else{ + return false; + } + } + } + return markStack.size()==0; + } + + private static boolean validation(String s){ + + if(s!=null&&s.length()>0){ + if(s.contains("(")&&s.contains(")")){ + return true; + } + if(s.contains("[")&&s.contains("]")){ + return true; + } + if(s.contains("{")&&s.contains("}")){ + return true; + } + } + return false; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..9d34a17fb5 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,174 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.Iterator; +import com.coding.basic.stack.Stack; +import com.coding.basic.stack.StackUtil; + +public class InfixExpr { + + String expr = null; + char[] data = null; + + private static final String operatorsStr = "+-*/"; + + public InfixExpr(String expr) { + this.expr = expr; + this.data = expr.toCharArray(); + } + + public float evaluate() { + + //数据栈 + Stack dataStack = new Stack<>(); + //操作栈 + Stack operStack = new Stack<>(); + + splitInfixExpr(dataStack,operStack); + + return summary(dataStack,operStack); + } + + + /** + * 拆分数据与运算符于两个栈中 + * + * @return + */ + private void splitInfixExpr(Stack dataStack,Stack operStack) { + + Itr it = new Itr(); + while(it.hasNext()){ + String element = it.next(); + if (operatorsStr.contains(element)) { + putOpersToStack(dataStack,operStack, element); + } else { + dataStack.push(Float.parseFloat(element)); + } + } + validationLastOpers(dataStack,operStack); + } + + /** + * 检查最后一个操作符优先级与之前是否保持统一, + * 若不统一则进行运算,使栈中运算符保持同一个优先级 + * @param stacks + */ + private void validationLastOpers(Stack dataStack,Stack operStack) { + + Object[] opers = StackUtil.getTop(operStack, 2); + Operator thisOper = (Operator) opers[0]; + Operator preOper = (Operator) opers[1]; + if(thisOper.getLevel()!=preOper.getLevel()){ + calculateToStack(dataStack,operStack,false); + } + } + + /** + * 运算符压栈 + * @param stacks + * @param c + */ + private void putOpersToStack(Stack dataStack,Stack operStack, String c) { + + Operator thisOper = Operator.getOperator(c); + if (!operStack.isEmpty()) { + Operator preOper = operStack.peek(); + if (preOper.getLevel() > thisOper.getLevel()) { + calculateToStack(dataStack,operStack,false); + } + } + operStack.push(thisOper); + } + + /** + * 运算 + * @param a 数字 + * @param oper 运算符 + * @param b 数字 + * @return + */ + private float calculate(float a,Operator oper,float b) { + + String operFlag = oper.getFlag(); + + float res = 0f; + if (Operator.ADD.getFlag().equals(operFlag)) { + res = a + b; + } else if (Operator.SUB.getFlag().equals(operFlag)) { + res = a - b; + } else if (Operator.MULTY.getFlag().equals(operFlag)) { + res = a * b; + } else if (Operator.DIVIDE.getFlag().equals(operFlag)) { + res = a / b; + } + return res; + } + + /** + * 运算距栈顶最近两个元素的值并压回原栈 + * @param stacks + * stacks[0]运算符,stacks[1]数据 + * @param isReverse + * 当isReversed为true时会交换两个元素的位置 + */ + private void calculateToStack(Stack dataStack,Stack operStack,boolean isReverse){ + + float a,b; + if(isReverse){ + a = dataStack.pop(); + b = dataStack.pop();; + }else{ + b = dataStack.pop();; + a = dataStack.pop();; + } + + Operator oper = operStack.pop(); + float res = calculate(a,oper,b); + dataStack.push(res); + } + + /** + * 汇总结果 + * @param stacks + * @return + */ + private float summary(Stack dataStack,Stack operStack) { + + StackUtil.reverse(dataStack); + StackUtil.reverse(operStack); + + while (!operStack.isEmpty()) { + calculateToStack(dataStack,operStack,true); + } + return dataStack.pop(); + } + + private class Itr implements Iterator { + + int cursor; + + @Override + public boolean hasNext() { + return cursor != (expr.length()); + } + + @Override + public String next() { + + StringBuilder val = new StringBuilder(); + for (int i = cursor; i < data.length; i++) { + if (operatorsStr.contains(data[i] + "")) { + if ("".equals(val.toString())) { + val.append(data[i]); + this.cursor = (i + 1); + } + break; + } else { + val.append(data[i]); + this.cursor = (i + 1); + } + } + return val.toString(); + } + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java new file mode 100644 index 0000000000..3629e99482 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +public enum Operator { + + ADD("+",1),SUB("-",1),MULTY("*",2),DIVIDE("/",2); + + private String flag; + private int level; + + private Operator(String flag,int level){ + this.flag = flag; + this.level = level; + } + + public static int getLevelByFlag(String flag){ + + Operator[] opers = Operator.values(); + for (Operator operator : opers) { + if(operator.flag.equals(flag)){ + return operator.level; + } + } + return -1; + } + + public static Operator getOperator(String flag){ + + if(ADD.flag.equals(flag)){ + return ADD; + }else if(SUB.flag.equals(flag)){ + return SUB; + }else if(MULTY.flag.equals(flag)){ + return MULTY; + }else if(DIVIDE.flag.equals(flag)){ + return DIVIDE; + } + return null; + } + + public String getFlag() { + return flag; + } + + public int getLevel() { + return level; + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java new file mode 100644 index 0000000000..3f763912fc --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java @@ -0,0 +1,271 @@ +package test.com.coderising.jvm; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.exception.NotAClassFileException; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "test/com/coderising/jvm/EmployeeV1"; + + //static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + static String path1 = "E:\\githubRepository\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + static String path2 = "C:\temp"; + + + static ClassFile clzFile = null; + static { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "test.com.coderising.jvm.EmployeeV1"; + + try { + clzFile = loader.loadClass(className); + } catch (NotAClassFileException e) { + e.printStackTrace(); + } + clzFile.print(); + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "test.com.coderising.jvm.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "test.com.coderising.jvm.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + @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(); + CodeAttr codeAttr = (CodeAttr)m.getAttributeInfos().get(0); + String code = codeAttr.getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/EmployeeV1.java b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/EmployeeV1.java similarity index 81% rename from group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/EmployeeV1.java rename to group12/2258659044/zj-2017/src/test/com/coderising/jvm/EmployeeV1.java index 463fb4a15f..9692355ed6 100644 --- a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/EmployeeV1.java +++ b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/EmployeeV1.java @@ -1,11 +1,11 @@ -package test.com.coderising.jvm.loader; +package test.com.coderising.jvm; +@SuppressWarnings("unused") public class EmployeeV1 { - - + private String name; - private int age; - + private int age ; + public EmployeeV1(String name, int age) { this.name = name; this.age = age; diff --git a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/ClassFileloaderTest.java b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/ClassFileloaderTest.java deleted file mode 100644 index b274338091..0000000000 --- a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/loader/ClassFileloaderTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package test.com.coderising.jvm.loader; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coderising.jvm.loader.ClassFileLoader; - -public class ClassFileloaderTest { - - static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; - static String path2 = "C:\temp"; - - - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testClassPath(){ - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - loader.addClassPath(path2); - - String clzPath = loader.getClassPath(); - - Assert.assertEquals(path1+";"+path2,clzPath); - - } - - @Test - public void testClassFileLength() { - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - - String className = "test.com.coderising.jvm.loader.EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1070, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "test.com.coderising.jvm.loader.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; - - - String acctualValue = this.byteToHexString(codes); - - Assert.assertEquals("cafebabe", acctualValue); - } - - - - - - - private String byteToHexString(byte[] codes ){ - StringBuffer buffer = new StringBuffer(); - for(int i=0;i node = tree.insert(4); + Assert.assertEquals((int)node.getParent().getData(), 2); + Assert.assertEquals((int)node.getParent().getLeft().getData(), 1); + + BinaryTreeNode node2 = tree.insert(8); + Assert.assertEquals((int)node2.getParent().getData(), 7); + Assert.assertEquals((int)node2.getParent().getLeft().getData(), 6); + } + + @Test + public void traversal(){ + + insert(); + //以根节点为起点先序遍历 + List treeList = tree.traversalBefore(tree.getRoot()); + //expected value + int[] exValue = {5,2,1,4,7,6,8}; + for (int i = 0; i < exValue.length; i++) { + Assert.assertEquals((int)treeList.get(i),exValue[i]); + } + + //以数据2位起点先序遍历 + List treeList2 = tree.traversalBefore(tree.getRoot().getLeft()); + //expected value + int[] exValue2 = {2,1,4}; + for (int i = 0; i < exValue2.length; i++) { + Assert.assertEquals((int)treeList2.get(i),exValue2[i]); + } + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java index 75af57b371..b12d23cdbd 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java @@ -1,64 +1,64 @@ -package test.com.coding.basic; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coding.basic.Queue; - -public class QueueTest { - - Queue qe ; - - @Before - public void setup() { - qe = new Queue(); - for (int i = 0; i < 10; i++) { - qe.enQueue(i); - } - } - - @Test - public void enQueue(){ - - Assert.assertEquals(qe.size(), 10); - qe.enQueue("abcd"); - Assert.assertEquals(qe.size(), 11); - } - - @Test//(expected = IndexOutOfBoundsException.class) - public void deQueue(){ - - Assert.assertEquals(qe.size(), 10); - for (int i = 0; i < 10; i++) { - Assert.assertEquals(qe.deQueue(), i); - } - Assert.assertEquals(qe.size(), 0); - //打开下列语句与期望异常测试 - //qe.deQueue(); - } - - public void isEmpty(){ - - Assert.assertEquals(qe.isEmpty(),false); - for (int i = 0; i < 10; i++) { - qe.deQueue(); - } - Assert.assertEquals(qe.isEmpty(),true); - Queue qe1 = new Queue(); - Assert.assertEquals(qe1.isEmpty(), true); - } - - public void size(){ - - Assert.assertEquals(qe.size(),10); - qe.enQueue("lk"); - qe.enQueue('h'); - Assert.assertEquals(qe.size(),12); - for (int i = 0; i < 12; i++) { - qe.deQueue(); - } - Assert.assertEquals(qe.size(),0); - Queue qe1 = new Queue(); - Assert.assertEquals(qe1.size(), 0); - } -} +package test.com.coding.basic; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.Queue; + +public class QueueTest { + + Queue qe ; + + @Before + public void setup() { + qe = new Queue<>(); + for (int i = 0; i < 10; i++) { + qe.enQueue(i); + } + } + + @Test + public void enQueue(){ + + Assert.assertEquals(qe.size(), 10); + qe.enQueue("abcd"); + Assert.assertEquals(qe.size(), 11); + } + + @Test//(expected = IndexOutOfBoundsException.class) + public void deQueue(){ + + Assert.assertEquals(qe.size(), 10); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(qe.deQueue(), i); + } + Assert.assertEquals(qe.size(), 0); + //打开下列语句与期望异常测试 + //qe.deQueue(); + } + + public void isEmpty(){ + + Assert.assertEquals(qe.isEmpty(),false); + for (int i = 0; i < 10; i++) { + qe.deQueue(); + } + Assert.assertEquals(qe.isEmpty(),true); + Queue qe1 = new Queue<>(); + Assert.assertEquals(qe1.isEmpty(), true); + } + + public void size(){ + + Assert.assertEquals(qe.size(),10); + qe.enQueue("lk"); + qe.enQueue('h'); + Assert.assertEquals(qe.size(),12); + for (int i = 0; i < 12; i++) { + qe.deQueue(); + } + Assert.assertEquals(qe.size(),0); + Queue qe1 = new Queue<>(); + Assert.assertEquals(qe1.size(), 0); + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayListTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayListTest.java index 9c4d91e8b3..ee20d2e038 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayListTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayListTest.java @@ -9,10 +9,10 @@ public class ArrayListTest { - ArrayList ls ; + ArrayList ls ; @Before public void setup() { - ls = new ArrayList(); + ls = new ArrayList<>(); } /** diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayUtilTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayUtilTest.java index e8303b8aba..c7dce9c1aa 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayUtilTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/array/ArrayUtilTest.java @@ -94,7 +94,7 @@ public void testJoin() { @Test public void testObjList2int() { - ArrayList ls = new ArrayList(); + ArrayList ls = new ArrayList<>(); for (int i = 0; i < 10; i++) { ls.add(i); } diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/linklist/LinkedListTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/linklist/LinkedListTest.java index 9a6e86000e..26d95dbc98 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/linklist/LinkedListTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/linklist/LinkedListTest.java @@ -9,10 +9,10 @@ public class LinkedListTest { - LinkedList ls ; + LinkedList ls ; @Before public void setup() { - ls = new LinkedList(); + ls = new LinkedList<>(); } /** @@ -169,7 +169,7 @@ public void testGetElements(){ ls.add(201);ls.add(301); ls.add(401);ls.add(501); ls.add(601);ls.add(701); - LinkedList list = new LinkedList(); + LinkedList list = new LinkedList<>(); list.add(1);list.add(3); list.add(4);list.add(6); int[] exceptArr = {101,301,401,601}; @@ -189,7 +189,7 @@ public void testSubtract(){ ls.add(8); ls.add(10); - LinkedList list = new LinkedList(); + LinkedList list = new LinkedList<>(); list.add(2); list.add(5); @@ -236,19 +236,19 @@ public void testIntersection(){ ls.add(3); ls.add(5); - LinkedList list = new LinkedList(); + LinkedList list = new LinkedList<>(); list.add(-1); list.add(0); list.add(5); list.add(9); - LinkedList newList = ls.intersection(list); + LinkedList newList = ls.intersection(list); int[] exceptArr = {-1,0,5}; exceptResult(newList,exceptArr); } - private void exceptResult(LinkedList ls,int[] exceptArr){ + private void exceptResult(LinkedList ls,int[] exceptArr){ Assert.assertEquals(ls.size(), exceptArr.length); for (int i = 0; i < exceptArr.length; i++) { diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/StackTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackTest.java similarity index 82% rename from group12/2258659044/zj-2017/src/test/com/coding/basic/StackTest.java rename to group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackTest.java index 5d9fcd0f16..d43b6f1914 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/StackTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackTest.java @@ -1,76 +1,76 @@ -package test.com.coding.basic; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coding.basic.Stack; - -public class StackTest { - - Stack st ; - - @Before - public void setup() { - st = new Stack(); - for (int i = 0; i < 10; i++) { - st.push(i); - } - } - - @Test - public void push(){ - - Assert.assertEquals(st.size(), 10); - st.push(10); - st.push('a'); - Assert.assertEquals(st.size(), 12); - } - - @Test//(expected = IndexOutOfBoundsException.class) - public void pop(){ - - Assert.assertEquals(st.size(), 10); - for (int i = 9; i >= 0; i--) { - Assert.assertEquals(st.pop(), i); - } - //打开下列语句抛出期望异常 - //st.pop(); - } - - @Test - public void peek(){ - - Assert.assertEquals(st.size(), 10); - Assert.assertEquals(st.peek(), 9); - Assert.assertEquals(st.size(), 10); - } - - @Test - public void isEmpty(){ - - Assert.assertEquals(st.isEmpty(), false); - for (int i = 0; i < 10; i++) { - st.pop(); - } - Assert.assertEquals(st.isEmpty(), true); - Stack st1 = new Stack(); - Assert.assertEquals(st1.isEmpty(), true); - } - - public void size(){ - - Assert.assertEquals(st.size(),10); - st.push("lk"); - st.push('h'); - Assert.assertEquals(st.size(),12); - for (int i = 0; i < 12; i++) { - st.pop(); - } - Assert.assertEquals(st.size(),0); - st.peek(); - Assert.assertEquals(st.size(),0); - Stack st1 = new Stack(); - Assert.assertEquals(st1.size(), 0); - } -} +package test.com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.Stack; + +public class StackTest { + + Stack st ; + + @Before + public void setup() { + st = new Stack<>(); + for (int i = 0; i < 10; i++) { + st.push(i); + } + } + + @Test + public void push(){ + + Assert.assertEquals(st.size(), 10); + st.push(10); + st.push('a'); + Assert.assertEquals(st.size(), 12); + } + + @Test//(expected = IndexOutOfBoundsException.class) + public void pop(){ + + Assert.assertEquals(st.size(), 10); + for (int i = 9; i >= 0; i--) { + Assert.assertEquals(st.pop(), i); + } + //打开下列语句抛出期望异常 + //st.pop(); + } + + @Test + public void peek(){ + + Assert.assertEquals(st.size(), 10); + Assert.assertEquals(st.peek(), 9); + Assert.assertEquals(st.size(), 10); + } + + @Test + public void isEmpty(){ + + Assert.assertEquals(st.isEmpty(), false); + for (int i = 0; i < 10; i++) { + st.pop(); + } + Assert.assertEquals(st.isEmpty(), true); + Stack st1 = new Stack<>(); + Assert.assertEquals(st1.isEmpty(), true); + } + + public void size(){ + + Assert.assertEquals(st.size(),10); + st.push("lk"); + st.push('h'); + Assert.assertEquals(st.size(),12); + for (int i = 0; i < 12; i++) { + st.pop(); + } + Assert.assertEquals(st.size(),0); + st.peek(); + Assert.assertEquals(st.size(),0); + Stack st1 = new Stack<>(); + Assert.assertEquals(st1.size(), 0); + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackUtilTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..d09f893de2 --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,95 @@ +package test.com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.Stack; +import com.coding.basic.stack.StackUtil; + +public class StackUtilTest { + + Stack s ; + + @Before + public void setup() { + //初始化栈元素:5,4,3,2,1 + s = new Stack<>(); + for (int i = 1; i <= 5; i++) { + s.push(i); + } + } + + @Test + public void testReverse() { + + StackUtil.reverse(s); + Assert.assertEquals(s.size(), 5); + Assert.assertEquals("[1,2,3,4,5]", s.toString()); + } + + @Test + public void testRemove() { + + StackUtil.remove(s, 5); + Assert.assertEquals("[4,3,2,1]", s.toString()); + + StackUtil.remove(s, 1); + Assert.assertEquals("[4,3,2]", s.toString()); + + StackUtil.remove(s, 4); + Assert.assertEquals("[3,2]", s.toString()); + } + + @Test + public void testGetTop() { + + Object[] obj = StackUtil.getTop(s, 6); + Assert.assertEquals(5, obj.length); + Assert.assertEquals(s.toString(),arrayToString(obj)); + + Object[] obj1 = StackUtil.getTop(s, 2); + Assert.assertEquals(2, obj1.length); + Assert.assertEquals("[5,4]",arrayToString(obj1)); + + } + + @Test + public void testIsValidPairs() { + + String s0 = "([e{d}f])"; + Assert.assertEquals(true,StackUtil.isValidPairs(s0)); + + String s1 = "(]e{d}f[)"; + Assert.assertEquals(false,StackUtil.isValidPairs(s1)); + + String s2 = "([b{x]y})"; + Assert.assertEquals(false,StackUtil.isValidPairs(s2)); + + String s3 = "()((()()))()"; + Assert.assertEquals(true,StackUtil.isValidPairs(s3)); + + String s4 = "(fs{fs[fs("; + Assert.assertEquals(false,StackUtil.isValidPairs(s4)); + + String s5 = "gshsg54fs"; + Assert.assertEquals(false,StackUtil.isValidPairs(s5)); + + + } + + private static String arrayToString(Object[] objs){ + + StringBuffer sBuffer = new StringBuffer(); + sBuffer.append("["); + + for (int i = 0; i < objs.length; i++) { + if(i == objs.length-1){ + sBuffer.append(objs[i]+"]"); + }else{ + sBuffer.append(objs[i]+","); + } + } + return sBuffer.toString(); + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/InfixExprTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..d22f51a98b --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package test.com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.expr.InfixExpr; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } +} From 159838d883b7930536f87d9d8125dba0617e0716 Mon Sep 17 00:00:00 2001 From: onlyLYJ <382266293@qq.com> Date: Mon, 17 Apr 2017 21:44:12 +0800 Subject: [PATCH 052/151] new work --- .../coding/basic/stack/expr/InfixExpr.java | 2 +- .../basic/stack/expr/InfixToPostfix.java | 14 ++ .../coding/basic/stack/expr/PostfixExpr.java | 18 +++ .../basic/stack/expr/PostfixExprTest.java | 41 +++++ .../coding/basic/stack/expr/PrefixExpr.java | 18 +++ .../basic/stack/expr/PrefixExprTest.java | 45 ++++++ .../coding/basic/stack/expr/TParser.java | 85 +++++++++++ .../coding/basic/stack/expr/Token.java | 50 ++++++ .../coding/basic/stack/expr/TokenParser.java | 143 +++++++----------- .../basic/stack/expr/TokenParserTest.java | 41 +++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 31 ++-- .../jvm/attr/LocalVariableTable.java | 15 ++ .../src/com/coderising/jvm/clz/ClassFile.java | 11 ++ .../src/com/coderising/jvm/cmd/BiPushCmd.java | 23 +++ .../coderising/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++ .../com/coderising/jvm/cmd/CommandParser.java | 85 +++++++++++ .../com/coderising/jvm/cmd/GetFieldCmd.java | 22 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 23 +++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 23 +++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../src/com/coderising/jvm/cmd/LdcCmd.java | 29 ++++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 23 +++ .../com/coderising/jvm/cmd/OneOperandCmd.java | 27 ++++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 19 +++ .../com/coderising/jvm/cmd/TwoOperandCmd.java | 67 ++++++++ .../jvm/loader/ClassFileParser.java | 2 - .../src/com/coderising/jvm/method/Method.java | 52 +++++-- .../jvm/test/ClassFileloaderTest.java | 78 ++++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 48 +++--- 30 files changed, 1071 insertions(+), 133 deletions(-) create mode 100644 group12/382266293/coding/basic/stack/expr/InfixToPostfix.java create mode 100644 group12/382266293/coding/basic/stack/expr/PostfixExpr.java create mode 100644 group12/382266293/coding/basic/stack/expr/PostfixExprTest.java create mode 100644 group12/382266293/coding/basic/stack/expr/PrefixExpr.java create mode 100644 group12/382266293/coding/basic/stack/expr/PrefixExprTest.java create mode 100644 group12/382266293/coding/basic/stack/expr/TParser.java create mode 100644 group12/382266293/coding/basic/stack/expr/Token.java create mode 100644 group12/382266293/coding/basic/stack/expr/TokenParserTest.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group12/382266293/src/com/coderising/jvm/cmd/TwoOperandCmd.java diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 2b4d531c40..0d23091ab1 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -12,7 +12,7 @@ public InfixExpr(String expr) { public float evaluate() { - TokenParser tp = new TokenParser(); + TParser tp = new TParser(); tp.parse(expr); Stack ints = new Stack(); Stack signs = new Stack(); diff --git a/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java b/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..790984607f --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,14 @@ +package stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} diff --git a/group12/382266293/coding/basic/stack/expr/PostfixExpr.java b/group12/382266293/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..30682ae05d --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,18 @@ +package 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/group12/382266293/coding/basic/stack/expr/PostfixExprTest.java b/group12/382266293/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..1a6137e537 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package 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/group12/382266293/coding/basic/stack/expr/PrefixExpr.java b/group12/382266293/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..96bef48492 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,18 @@ +package stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group12/382266293/coding/basic/stack/expr/PrefixExprTest.java b/group12/382266293/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..85b68a1020 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package 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/group12/382266293/coding/basic/stack/expr/TParser.java b/group12/382266293/coding/basic/stack/expr/TParser.java new file mode 100644 index 0000000000..06c543efd3 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/TParser.java @@ -0,0 +1,85 @@ +package stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingDeque; + +public class TParser { + + Queue intQ; + Queue signQ; + static final List signs = new ArrayList(); + { + signs.add("+"); + signs.add("-"); + signs.add("*"); + signs.add("/"); + } + + public TParser() { + intQ = new LinkedBlockingDeque(); + signQ = new LinkedBlockingDeque(); + } + + public void parse(String expr) { + + String[] tokens = expr.split(""); + String number = ""; + + for (int i = 0; i < tokens.length; i++) { + + String c = tokens[i]; + + if (isSign(c)) { + + signQ.add(c); + + int num = Integer.parseInt(number); + intQ.add(num); + number = ""; + + } else { + + number += tokens[i]; + + } + + } + + int num = Integer.parseInt(number); + intQ.add(num); + + int intSize = intQ.size(); + if (intSize < 2 || intSize - signQ.size() > 1) { + throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); + } + + intQ.add(0); + + } + + private boolean isSign(String c) { + if (signs.contains(c)) { + return true; + } + return false; + } + + public int nextInt() { + return intQ.poll(); + } + + public String nextSign() { + return signQ.poll(); + } + + public boolean hasNextInt() { + return !intQ.isEmpty(); + } + + public boolean hasNextSign() { + return !signQ.isEmpty(); + } + +} diff --git a/group12/382266293/coding/basic/stack/expr/Token.java b/group12/382266293/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..203f91d61f --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package 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 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/group12/382266293/coding/basic/stack/expr/TokenParser.java b/group12/382266293/coding/basic/stack/expr/TokenParser.java index 4fa0d7b79e..5f4be41e00 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParser.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParser.java @@ -1,86 +1,57 @@ -package stack.expr; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.LinkedBlockingDeque; - -public class TokenParser { - - Queue intQ; - Queue signQ; - static final List signs = new ArrayList(); - { - signs.add("+"); - signs.add("-"); - signs.add("*"); - signs.add("/"); - } - - public TokenParser() { - intQ = new LinkedBlockingDeque(); - signQ = new LinkedBlockingDeque(); - } - - public void parse(String expr) { - - String[] tokens = expr.split(""); - String number = ""; - String sign = ""; - - for (int i = 0; i < tokens.length; i++) { - - String c = tokens[i]; - - if (isSign(c)) { - sign = c; - signQ.add(sign); - if (!number.equals("")) { - int num = Integer.parseInt(number); - intQ.add(num); - number = ""; - } - } else { - number += tokens[i]; - } - - } - - if (!number.equals("")) { - int num = Integer.parseInt(number); - intQ.add(num); - } - - int intSize = intQ.size(); - if (intSize < 2 || intSize - signQ.size() > 1) { - throw new RuntimeException("Invalid input IntQ: " + intQ + " signQ " + signQ); - } - - intQ.add(0); - - } - - private boolean isSign(String c) { - if (signs.contains(c)) { - return true; - } - return false; - } - - public int nextInt() { - return intQ.poll(); - } - - public String nextSign() { - return signQ.poll(); - } - - public boolean hasNextInt() { - return !intQ.isEmpty(); - } - - public boolean hasNextSign() { - return !signQ.isEmpty(); - } - -} +package 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/group12/382266293/coding/basic/stack/expr/TokenParserTest.java b/group12/382266293/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..22dd219fb7 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package stack.expr; + +import static org.junit.Assert.*; + +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()); + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java index da9c2899a2..6ccca5f5cf 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java @@ -1,6 +1,9 @@ package com.coderising.jvm.attr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; @@ -20,7 +23,8 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ String code = iter.nextUxToHexString(codeLen); - 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); System.out.println("Code is " + code); @@ -70,21 +74,17 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ private int codeLen ; private String 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*/) { + 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 String getCode() { @@ -105,8 +105,21 @@ private void setStackMapTable(StackMapTable t) { } - - + private ByteCodeCommand[] cmds ; + public ByteCodeCommand[] getCmds() { + return cmds; + } + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + //buffer.append("Code:").append(code).append("\n"); + for(int i=0;i methods) { public void setMinorVersion(int minorVersion) { this.minorVersion = minorVersion; } + + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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(); + } + + + +} diff --git a/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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); +} diff --git a/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java b/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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(); + } + + } +} diff --git a/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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); + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.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); + } + + + +} diff --git a/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/382266293/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java index b29cfe1d45..c20fbfe855 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java @@ -174,8 +174,6 @@ private void parseInterfaces(ByteCodeIterator iter) { private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { int methodNum = iter.nextU2ToInt(); - - ConstantPool pool = clzFile.getConstantPool(); for (int i = 0; i < methodNum; i++) { Method method = Method.parse(clzFile,iter); clzFile.addMethod(method); diff --git a/group12/382266293/src/com/coderising/jvm/method/Method.java b/group12/382266293/src/com/coderising/jvm/method/Method.java index 705ec22792..2bb53cdf06 100644 --- a/group12/382266293/src/com/coderising/jvm/method/Method.java +++ b/group12/382266293/src/com/coderising/jvm/method/Method.java @@ -3,11 +3,32 @@ import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public class Method { + + + private int accessFlag; + private int nameIndex; + + private int descriptorIndex; + + private CodeAttr codeAttr; + + + private ClassFile clzFile; + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ @@ -39,22 +60,17 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return method; } - private int accessFlag; - private int nameIndex; - private int descriptorIndex; - private CodeAttr codeAttr; - private ClassFile clzFile; - public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { - this.clzFile = clzFile; - this.accessFlag = accessFlag; - this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; + + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); } + public ClassFile getClzFile() { return clzFile; } @@ -75,4 +91,20 @@ public int getNameIndex() { public void setCodeAttr(CodeAttr code) { this.codeAttr = code; } + + 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(); + } } diff --git a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java index 15050a0d76..883ad99c05 100644 --- a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -10,6 +10,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; @@ -260,5 +264,79 @@ public void testVersion() { } + @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/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java b/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java index 24c0cae543..9a36573dd3 100644 --- a/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java +++ b/group12/382266293/src/com/coderising/jvm/test/EmployeeV1.java @@ -1,30 +1,28 @@ package com.coderising.jvm.test; public class EmployeeV1 { - - public static void main(String[] args) { - EmployeeV1 p = new EmployeeV1("Andy", 29); - p.sayHello(); - - } + + private String name; - - private int age; - - public EmployeeV1(String name, int age) { - this.name = name; - this.age = age; - } - - public void sayHello() { - System.out.println("Hello , this is class Employee "); - } - - public void setAge(int age) { - this.age = age; - } - - public void setName(String name) { - this.name = name; - } + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } } \ No newline at end of file From f33c43704415a5d775e06cb10b4936015999f522 Mon Sep 17 00:00:00 2001 From: sdnb Date: Mon, 17 Apr 2017 22:06:17 +0800 Subject: [PATCH 053/151] =?UTF-8?q?=E7=AC=AC=E5=85=AD=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/attr/AttributeInfo.java | 19 +++ .../src/com/coderising/jvm/attr/CodeAttr.java | 89 ++++++++++++ .../coderising/jvm/attr/LineNumberTable.java | 52 +++++++ .../jvm/attr/LocalVariableItem.java | 39 ++++++ .../jvm/attr/LocalVariableTable.java | 39 ++++++ .../coderising/jvm/attr/StackMapTable.java | 30 +++++ .../src/com/coderising/jvm/clz/ClassFile.java | 41 ++++-- .../src/com/coderising/jvm/field/Field.java | 38 ++++++ .../jvm/loader/ByteCodeIterator.java | 22 ++- .../jvm/loader/ClassFileParser.java | 31 ++++- .../src/com/coderising/jvm/method/Method.java | 66 +++++++++ .../src/main/java/com/coding/weak1/Stack.java | 2 + .../java/com/coding/week6/expr/InfixExpr.java | 127 ++++++++++++++++++ .../java/com/coding/week6/expr/Token.java | 52 +++++++ .../mini_jvm/test/ClassFileloaderTest.java | 84 +++++++++++- .../coding/week6/expr/InfixExprTestTest.java | 77 +++++++++++ 16 files changed, 784 insertions(+), 24 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java create mode 100644 group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java create mode 100644 group24/494800949/src/main/java/com/coding/week6/expr/Token.java create mode 100644 group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..7db7a49c32 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..ee04b856d7 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,89 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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){ + + //回退2个字节 + iter.back(ByteCodeIterator.U2); + int attrNameIndex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + int maxStack = iter.readTwoBytesToInt(); + int maxLocal = iter.readTwoBytesToInt(); + int codeLen = iter.readFourBytesToInt(); + String code = iter.readBytesToString(codeLen); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocal, codeLen, code); + + //异常表长度 + int exceptionTableLen = iter.readTwoBytesToInt(); + if (exceptionTableLen > 0) { + throw new RuntimeException("not impl yet"); + } + + //子属性个数 + int attrCount = iter.readTwoBytesToInt(); + for (int i = 0; i < attrCount; i++) { + attrNameIndex = iter.readTwoBytesToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + if ("LineNumberTable".equals(attrName)) { + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + } else if ("LocalVariableTable".equals(attrName)) { + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + } else if ("StackMapTable".equals(attrName)) { + StackMapTable stackMapTable = StackMapTable.parse(iter); + codeAttr.setStackMapTable(stackMapTable); + } else { + throw new RuntimeException("not impl yet"); + } + } + + return codeAttr; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + } + + + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..93e7d9b7a8 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,52 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + + +public class LineNumberTable extends AttributeInfo { + List 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){ + iter.back(ByteCodeIterator.U2); + int attrNameIndex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLen); + int itemCount = iter.readTwoBytesToInt(); + for (int i = 0; i < itemCount; i++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.readTwoBytesToInt()); + lineNumberItem.setLineNum(iter.readTwoBytesToInt()); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; + } + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..9e9e1d9e21 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..2900349fa5 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,39 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.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); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + iter.back(ByteCodeIterator.U2); + int attrNameIdex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIdex, attrLen); + int varCount = iter.readTwoBytesToInt(); + for (int i = 0; i < varCount; i++) { + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.readTwoBytesToInt()); + item.setLength(iter.readTwoBytesToInt()); + item.setNameIndex(iter.readTwoBytesToInt()); + item.setDescIndex(iter.readTwoBytesToInt()); + item.setIndex(iter.readTwoBytesToInt()); + localVariableTable.addLocalVariableItem(item); + } + return localVariableTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..a6e55353f1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.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){ + iter.back(ByteCodeIterator.U2); + int index = iter.readTwoBytesToInt(); + int len = iter.readFourBytesToInt(); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.readBytesToString(len); + t.setOriginalCode(code); + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java index 0d2525e416..047c65195f 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -3,28 +3,50 @@ import com.coding.mini_jvm.src.com.coderising.jvm.constant.ClassInfo; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; public class ClassFile { - + private int minorVersion; private int majorVersion; - + private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; - - + private List fields = new ArrayList(); + private List methods = new ArrayList(); + public ClassIndex getClzIndex() { return clzIndex; } + public AccessFlag getAccessFlag() { return accessFlag; } + public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - + + 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 ConstantPool getConstantPool() { return pool; @@ -49,19 +71,12 @@ 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()); - - } private String getClassName(){ diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..18bcdb2851 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,38 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.field; + + +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + int accessFlag = iter.readTwoBytesToInt(); + int nameIndex = iter.readTwoBytesToInt(); + int descIndex = iter.readTwoBytesToInt(); + int attributesCount = iter.readTwoBytesToInt(); + if (attributesCount > 0) + throw new RuntimeException("attributeCount of field not impl"); + return new Field(accessFlag, nameIndex, descIndex, pool); + } + + + @Override + public String toString() { + return pool.getUTF8String(nameIndex)+":"+pool.getUTF8String(descriptorIndex); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java index 27d0c63af0..1fe59b5bdb 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -3,10 +3,10 @@ import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; public class ByteCodeIterator { - private static final int U1 = 1; - private static final int U2 = 2; - private static final int U4 = 4; - private static final int U8 = 8; + public static final int U1 = 1; + public static final int U2 = 2; + public static final int U4 = 4; + public static final int U8 = 8; private byte[] bytes; private int cursor; @@ -33,6 +33,12 @@ public int readTwoBytesToInt() { return ret; } + public int readFourBytesToInt() { + int ret = Util.bytes2Int(bytes, cursor, U4); + cursor += U4; + return ret; + } + public int readByteToInt() { int ret = Util.bytes2Int(bytes, cursor, U1); cursor += U1; @@ -49,4 +55,12 @@ public int skip(int len) { cursor += len; return cursor; } + + public int back(int len) { + if (cursor + len < 0 || cursor + len > bytes.length - 1) { + throw new IndexOutOfBoundsException(); + } + cursor -= len; + return cursor; + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java index 542968c809..afe40a2156 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -4,6 +4,8 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; public class ClassFileParser { @@ -18,11 +20,22 @@ public ClassFile parse(byte[] codes) { //主版本号 classFile.setMajorVersion(iterator.readTwoBytesToInt()); //解析常量池 - classFile.setConstPool(parseConstantPool(iterator)); + ConstantPool constantPool = parseConstantPool(iterator); + classFile.setConstPool(constantPool); //访问限制符 classFile.setAccessFlag(parseAccessFlag(iterator)); //当前类/父类 classFile.setClassIndex(parseClassIndex(iterator)); + + //接口数量暂时不实现 + int intefaceCount = iterator.readTwoBytesToInt(); + if (intefaceCount > 0) { + throw new RuntimeException(); + } + //解析字段 + parseFields(classFile,iterator, constantPool); + //解析方法 + parseMethod(classFile, iterator, constantPool); return classFile; } @@ -99,5 +112,19 @@ private ConstantPool parseConstantPool(ByteCodeIterator iterator) { return constantPool; } - + + private void parseFields(ClassFile classFile, ByteCodeIterator iterator, ConstantPool constantPool) { + int fieldCount = iterator.readTwoBytesToInt(); + for (int i = 0; i < fieldCount; i++) + classFile.addField(Field.parse(constantPool, iterator)); + } + + + private void parseMethod(ClassFile clzFile, ByteCodeIterator iter, ConstantPool pool) { + int methodCount = iter.readTwoBytesToInt(); + for (int i = 0; i < methodCount; i++) { + clzFile.addMethod(Method.parse(clzFile, iter)); + } + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..fd5734e6b6 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,66 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.method; + + +import com.coding.mini_jvm.src.com.coderising.jvm.attr.CodeAttr; +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.readTwoBytesToInt(); + int nameIndex = iter.readTwoBytesToInt(); + int descIndex = iter.readTwoBytesToInt(); + Method method = new Method(clzFile, accessFlag, nameIndex, descIndex); + System.out.println(clzFile.getConstantPool().getUTF8String(descIndex)); + int attrCount = iter.readTwoBytesToInt(); + if (attrCount > 1) + throw new RuntimeException("other attrbute not impl yet"); + for (int i = 0; i < attrCount; i++) { + int attrNameIndex = iter.readTwoBytesToInt(); + if ("Code".equals(clzFile.getConstantPool().getUTF8String(attrNameIndex))) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + } else + throw new RuntimeException("not impl yet"); + } + return method; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/weak1/Stack.java b/group24/494800949/src/main/java/com/coding/weak1/Stack.java index ffa00f99e7..0eecd9d684 100644 --- a/group24/494800949/src/main/java/com/coding/weak1/Stack.java +++ b/group24/494800949/src/main/java/com/coding/weak1/Stack.java @@ -18,6 +18,8 @@ public Object pop(){ } public Object peek(){ + if (size() == 0) + return null; return elementData.get(elementData.size()-1); } public boolean isEmpty(){ diff --git a/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java b/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java new file mode 100644 index 0000000000..34c1b15123 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java @@ -0,0 +1,127 @@ +package com.coding.week6.expr; + +import com.coding.weak1.Stack; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class InfixExpr { + String expr = null; + private Stack numberStack; + private Stack operatorStack; + private List tokens; + public InfixExpr(String expr) { + this.expr = expr; + this.numberStack = new Stack(); + this.operatorStack = new Stack(); + tokens = new ArrayList<>(); + } + + + public float evaluate() { + fillStack(); + while (!operatorStack.isEmpty()) { + char symbol = (char) operatorStack.pop(); + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(symbol, operTop2, operTop1)); + } + return (float)numberStack.pop(); + } + + public void parseTokens() { + char[] chars = expr.toCharArray(); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (Token.isOperator(c)) { + Token token = new Token(c+""); + tokens.add(token); + } else { + String t = ""; + while (Token.isDigit(c)){ + t += c; + i++; + if (i == chars.length) + break; + c = chars[i]; + } + Token token = new Token(t); + tokens.add(token); + i--; + } + } + } + + + public void fillStack() { + parseTokens(); + Iterator iterator = tokens.iterator(); + while (iterator.hasNext()) { + Token token = iterator.next(); + if (token.isNumber()) { + numberStack.push((float)token.parseInt()); + continue; + } + if (token.isOperator()) { + char operator = token.parseOperator(); + if (operatorStack.isEmpty()) { + operatorStack.push(operator); + }else { + char topSymbol = (char)operatorStack.peek(); + if (compare(operator, topSymbol) > 0) { + operatorStack.push(operator); + } else { + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(topSymbol, operTop2, operTop1)); + operatorStack.pop(); + operatorStack.push(operator); + } + } + } + + } + } + + + private float caculate(char symbol, float oper1, float oper2) { + if ('*' == symbol) + return oper1 * oper2; + else if ('/' == symbol) + return oper1 / oper2; + else if ('+' == symbol) + return oper1 + oper2; + else if ('-' == symbol) + return oper1 - oper2; + else + throw new RuntimeException("this operation has not implement"); + } + + public int compare(char opertor1, char opertor2) { + if (!Token.isOperator(opertor1) ) + throw new IllegalArgumentException(opertor1 + "is not supported opertor"); + if (!Token.isOperator(opertor2)) + throw new IllegalArgumentException(opertor2 + "is not supported opertor"); + if (Token.isAddOrSub(opertor1)) { + if (Token.isAddOrSub(opertor2)) + return 0; + else + return -1; + } + else { + if (Token.isAddOrSub(opertor2)) + return 1; + else + return 0; + } + } + + public String printNumberStack() { + return numberStack.toString(); + } + + public String printOperatorStack() { + return operatorStack.toString(); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week6/expr/Token.java b/group24/494800949/src/main/java/com/coding/week6/expr/Token.java new file mode 100644 index 0000000000..b58aa36968 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/expr/Token.java @@ -0,0 +1,52 @@ +package com.coding.week6.expr; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class Token { + + private String symbol; + + public Token(String symbol) { + this.symbol = symbol; + } + + public boolean isNumber() { + return symbol.matches("^\\d+$"); + } + + + public boolean isOperator() { + return symbol.matches("^[\\+|\\*|\\-|\\/]$"); + } + + public int parseInt() { + return Integer.valueOf(symbol); + } + + public char parseOperator() { + return symbol.charAt(0); + } + + + public static boolean isOperator(char c) { + return isAddOrSub(c) || isMulityOrDivide(c); + } + + public static boolean isAddOrSub(char c) { + return c == '+' || c == '-'; + } + + public static boolean isMulityOrDivide(char c) { + return c == '/' || c == '*'; + } + + public static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + @Override + public String toString(){ + return symbol; + } +} diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java index a03f29c0c3..00812bcd80 100644 --- a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java @@ -3,22 +3,22 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; - - - +import java.util.List; public class ClassFileloaderTest { - static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949\\build\\classes\\test"; + static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949"; static String path2 = "C:\temp"; private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; @@ -27,7 +27,7 @@ public class ClassFileloaderTest { static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coding.mini_jvm.test.EmployeeV1"; + String className = "EmployeeV1"; clzFile = loader.loadClass(className); // clzFile.print(); @@ -170,4 +170,78 @@ 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); + } } diff --git a/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java b/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java new file mode 100644 index 0000000000..7ef4b9ccfa --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java @@ -0,0 +1,77 @@ +package com.coding.week6.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class InfixExprTestTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + + + @Test + public void testFillStack() { + InfixExpr expr = new InfixExpr("10-30+50"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); + Assert.assertEquals(expr.printOperatorStack(), "+"); + expr = new InfixExpr("3*20+12*5-40/2"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "2.0,40.0,60.0,60.0"); + Assert.assertEquals(expr.printOperatorStack(), "/,-,+"); + expr = new InfixExpr("3*20/2"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "2.0,60.0"); + Assert.assertEquals(expr.printOperatorStack(), "/"); + expr = new InfixExpr("20/2*3"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "3.0,10.0"); + Assert.assertEquals(expr.printOperatorStack(), "*"); + expr = new InfixExpr("10-30+50"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); + Assert.assertEquals(expr.printOperatorStack(), "+"); + } + + + +} \ No newline at end of file From b62b5fb5d9ac212b84981ee299584e0c79de05c6 Mon Sep 17 00:00:00 2001 From: gongxun Date: Mon, 17 Apr 2017 23:39:47 +0800 Subject: [PATCH 054/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A04=E6=9C=8816=E6=97=A5?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.16/cmd/BiPushCmd.java | 20 +++ .../785396327/4.16/cmd/ByteCodeCommand.java | 129 ++++++++++++++++++ group17/785396327/4.16/cmd/CommandParser.java | 86 ++++++++++++ group17/785396327/4.16/cmd/GetFieldCmd.java | 20 +++ .../785396327/4.16/cmd/GetStaticFieldCmd.java | 20 +++ .../785396327/4.16/cmd/InvokeSpecialCmd.java | 20 +++ .../785396327/4.16/cmd/InvokeVirtualCmd.java | 19 +++ group17/785396327/4.16/cmd/LdcCmd.java | 30 ++++ group17/785396327/4.16/cmd/NewObjectCmd.java | 20 +++ group17/785396327/4.16/cmd/NoOperandCmd.java | 24 ++++ group17/785396327/4.16/cmd/OneOperandCmd.java | 27 ++++ group17/785396327/4.16/cmd/PutFieldCmd.java | 19 +++ group17/785396327/4.16/cmd/TwoOperandCmd.java | 65 +++++++++ group17/785396327/4.5/clz/ClassFile.java | 10 ++ .../4.5/test/ClassFileloaderTest.java | 80 +++++++++++ group17/785396327/4.9/attr/CodeAttr.java | 22 ++- group17/785396327/4.9/expr/ExprParser.java | 4 +- group17/785396327/4.9/method/Method.java | 5 + 18 files changed, 611 insertions(+), 9 deletions(-) create mode 100644 group17/785396327/4.16/cmd/BiPushCmd.java create mode 100644 group17/785396327/4.16/cmd/ByteCodeCommand.java create mode 100644 group17/785396327/4.16/cmd/CommandParser.java create mode 100644 group17/785396327/4.16/cmd/GetFieldCmd.java create mode 100644 group17/785396327/4.16/cmd/GetStaticFieldCmd.java create mode 100644 group17/785396327/4.16/cmd/InvokeSpecialCmd.java create mode 100644 group17/785396327/4.16/cmd/InvokeVirtualCmd.java create mode 100644 group17/785396327/4.16/cmd/LdcCmd.java create mode 100644 group17/785396327/4.16/cmd/NewObjectCmd.java create mode 100644 group17/785396327/4.16/cmd/NoOperandCmd.java create mode 100644 group17/785396327/4.16/cmd/OneOperandCmd.java create mode 100644 group17/785396327/4.16/cmd/PutFieldCmd.java create mode 100644 group17/785396327/4.16/cmd/TwoOperandCmd.java diff --git a/group17/785396327/4.16/cmd/BiPushCmd.java b/group17/785396327/4.16/cmd/BiPushCmd.java new file mode 100644 index 0000000000..e69c53310f --- /dev/null +++ b/group17/785396327/4.16/cmd/BiPushCmd.java @@ -0,0 +1,20 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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(); + } +} diff --git a/group17/785396327/4.16/cmd/ByteCodeCommand.java b/group17/785396327/4.16/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..97865bbd31 --- /dev/null +++ b/group17/785396327/4.16/cmd/ByteCodeCommand.java @@ -0,0 +1,129 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantInfo; +import constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by IBM on 2017/4/17. + */ +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); +} diff --git a/group17/785396327/4.16/cmd/CommandParser.java b/group17/785396327/4.16/cmd/CommandParser.java new file mode 100644 index 0000000000..35d9f80831 --- /dev/null +++ b/group17/785396327/4.16/cmd/CommandParser.java @@ -0,0 +1,86 @@ +package cmd; + +import clz.ClassFile; + +import java.util.List; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/GetFieldCmd.java b/group17/785396327/4.16/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..a255cef97b --- /dev/null +++ b/group17/785396327/4.16/cmd/GetFieldCmd.java @@ -0,0 +1,20 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/GetStaticFieldCmd.java b/group17/785396327/4.16/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..37ca3c7195 --- /dev/null +++ b/group17/785396327/4.16/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/InvokeSpecialCmd.java b/group17/785396327/4.16/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..80af63e860 --- /dev/null +++ b/group17/785396327/4.16/cmd/InvokeSpecialCmd.java @@ -0,0 +1,20 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/InvokeVirtualCmd.java b/group17/785396327/4.16/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..631e743c5f --- /dev/null +++ b/group17/785396327/4.16/cmd/InvokeVirtualCmd.java @@ -0,0 +1,19 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/LdcCmd.java b/group17/785396327/4.16/cmd/LdcCmd.java new file mode 100644 index 0000000000..183a4010de --- /dev/null +++ b/group17/785396327/4.16/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantInfo; +import constant.ConstantPool; +import constant.StringInfo; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/NewObjectCmd.java b/group17/785396327/4.16/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..6cd609aeb4 --- /dev/null +++ b/group17/785396327/4.16/cmd/NewObjectCmd.java @@ -0,0 +1,20 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/NoOperandCmd.java b/group17/785396327/4.16/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..7797d5218e --- /dev/null +++ b/group17/785396327/4.16/cmd/NoOperandCmd.java @@ -0,0 +1,24 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/OneOperandCmd.java b/group17/785396327/4.16/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..4f3dbc9feb --- /dev/null +++ b/group17/785396327/4.16/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package cmd; + +import clz.ClassFile; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/PutFieldCmd.java b/group17/785396327/4.16/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..07c88273cc --- /dev/null +++ b/group17/785396327/4.16/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package cmd; + +import clz.ClassFile; +import constant.ConstantPool; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.16/cmd/TwoOperandCmd.java b/group17/785396327/4.16/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..a12df75e52 --- /dev/null +++ b/group17/785396327/4.16/cmd/TwoOperandCmd.java @@ -0,0 +1,65 @@ +package cmd; + +import clz.ClassFile; +import constant.*; + +/** + * Created by IBM on 2017/4/17. + */ +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/group17/785396327/4.5/clz/ClassFile.java b/group17/785396327/4.5/clz/ClassFile.java index e65cfbda81..27e78451c5 100644 --- a/group17/785396327/4.5/clz/ClassFile.java +++ b/group17/785396327/4.5/clz/ClassFile.java @@ -91,4 +91,14 @@ private String getSuperClassName(){ ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } } diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 854453f2bd..3e4f3e100c 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -2,6 +2,10 @@ import clz.ClassFile; import clz.ClassIndex; +import cmd.BiPushCmd; +import cmd.ByteCodeCommand; +import cmd.OneOperandCmd; +import cmd.TwoOperandCmd; import constant.*; import field.Field; import jvm_1.ClassFileLoader; @@ -265,4 +269,80 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName 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/group17/785396327/4.9/attr/CodeAttr.java b/group17/785396327/4.9/attr/CodeAttr.java index 9e3505eb37..fb8e530b9b 100644 --- a/group17/785396327/4.9/attr/CodeAttr.java +++ b/group17/785396327/4.9/attr/CodeAttr.java @@ -1,6 +1,8 @@ package attr; import clz.ClassFile; +import cmd.ByteCodeCommand; +import cmd.CommandParser; import constant.ConstantInfo; import iterator.ByteCodeIterator; @@ -17,21 +19,24 @@ 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) { @@ -50,9 +55,12 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { int maxLocals = iter.nextU2ToInt(); int codeLength = iter.nextU4ToInt(); String code = iter.nextLengthString(codeLength); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + int exceptionTableLength = iter.nextU2ToInt();//跳过异常表 // System.out.println("Code属性表中的异常表元素大小:" + exceptionTableLength); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, cmds); int attributesCount = iter.nextU2ToInt(); //code属性表中又有属性 for (int i = 0; i < attributesCount; i++) { diff --git a/group17/785396327/4.9/expr/ExprParser.java b/group17/785396327/4.9/expr/ExprParser.java index a197377b4a..09a909fbad 100644 --- a/group17/785396327/4.9/expr/ExprParser.java +++ b/group17/785396327/4.9/expr/ExprParser.java @@ -16,7 +16,7 @@ public static List parse(InfixExpr infixExpr) { StringBuilder numberBuffer = new StringBuilder(); for (int i = 0; i < split.length; i++) { String ele = split[i]; - if (ele.equals(OperEnum.ADD.getOperator()) || ele.equals(OperEnum.SUBSTRACT.getOperator()) || ele.equals(OperEnum.MINUS.getOperator()) || ele.equals(OperEnum.MULTIPLY.getOperator())) { + if (ele.equals(OperEnum.ADD.getOperator()) || ele.equals(OperEnum.SUBTRACT.getOperator()) || ele.equals(OperEnum.MINUS.getOperator()) || ele.equals(OperEnum.MULTIPLY.getOperator())) { results.add(numberBuffer.toString()); numberBuffer.delete(0, numberBuffer.length()); results.add(ele); @@ -32,6 +32,6 @@ public static boolean belongsHighPriority(String operEle) { } public static boolean belongsOperator(String operEle) { - return (operEle != null) && (operEle.trim().equals(OperEnum.ADD.getOperator()) || operEle.trim().equals(OperEnum.SUBSTRACT.getOperator()) || operEle.trim().equals(OperEnum.MULTIPLY.getOperator()) || operEle.trim().equals(OperEnum.MINUS.getOperator())); + return (operEle != null) && (operEle.trim().equals(OperEnum.ADD.getOperator()) || operEle.trim().equals(OperEnum.SUBTRACT.getOperator()) || operEle.trim().equals(OperEnum.MULTIPLY.getOperator()) || operEle.trim().equals(OperEnum.MINUS.getOperator())); } } diff --git a/group17/785396327/4.9/method/Method.java b/group17/785396327/4.9/method/Method.java index 8a5fb59e09..1b5daa244b 100644 --- a/group17/785396327/4.9/method/Method.java +++ b/group17/785396327/4.9/method/Method.java @@ -2,6 +2,7 @@ import attr.CodeAttr; import clz.ClassFile; +import cmd.ByteCodeCommand; import iterator.ByteCodeIterator; import util.Util; @@ -59,4 +60,8 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { return method; } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } From bcf3efdc452a7ec38f3a368b6062a0659459f1e0 Mon Sep 17 00:00:00 2001 From: Admin Date: Tue, 18 Apr 2017 11:41:25 +0800 Subject: [PATCH 055/151] javap done --- .../src/com/coderising/jvm/attr/CodeAttr.java | 8 +- .../src/com/coderising/jvm/clz/ClassFile.java | 27 ++++- .../com/coderising/jvm/cmd/CommandParser.java | 98 ++++++++++++++++++- .../coderising/jvm/constant/ClassInfo.java | 8 ++ .../coderising/jvm/constant/ConstantInfo.java | 4 + .../coderising/jvm/constant/ConstantPool.java | 7 +- .../coderising/jvm/constant/FieldRefInfo.java | 7 ++ .../jvm/constant/MethodRefInfo.java | 7 ++ .../jvm/constant/NameAndTypeInfo.java | 7 ++ .../jvm/constant/NullConstantInfo.java | 11 +++ .../coderising/jvm/constant/StringInfo.java | 8 ++ .../com/coderising/jvm/constant/UTF8Info.java | 9 ++ .../jvm/loader/ClassFileParser.java | 5 +- .../jvm/print/ClassFilePrinter.java | 52 ++++++++++ .../jvm/print/ConstantPoolPrinter.java | 92 +++++++++++++++++ .../coderising/jvm/print/PrintVisitor.java | 23 +++++ 16 files changed, 363 insertions(+), 10 deletions(-) create mode 100644 group12/382266293/src/com/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java create mode 100644 group12/382266293/src/com/coderising/jvm/print/PrintVisitor.java diff --git a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java index 6ccca5f5cf..99c0183e02 100644 --- a/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java @@ -1,5 +1,7 @@ package com.coderising.jvm.attr; +import java.util.Arrays; + import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.cmd.ByteCodeCommand; import com.coderising.jvm.cmd.CommandParser; @@ -22,11 +24,12 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ System.out.println("codeLen " + codeLen); String code = iter.nextUxToHexString(codeLen); - + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, cmds); - System.out.println("Code is " + code); + System.out.println("Code is " + code); + System.out.println(Arrays.toString(cmds)); int exceptionTableLen = iter.nextU2ToInt(); @@ -109,6 +112,7 @@ private void setStackMapTable(StackMapTable t) { public ByteCodeCommand[] getCmds() { return cmds; } + public String toString(ConstantPool pool){ StringBuilder buffer = new StringBuilder(); //buffer.append("Code:").append(code).append("\n"); diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java index 256073d15d..111cb247d3 100644 --- a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java @@ -5,6 +5,7 @@ import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; @@ -35,7 +36,7 @@ public AccessFlag getAccessFlag() { return accessFlag; } - private String getClassName() { + public String getClassName() { int thisClassIndex = this.clzIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); @@ -67,7 +68,7 @@ public int getMinorVersion() { return minorVersion; } - private String getSuperClassName() { + public String getSuperClassName() { ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } @@ -118,12 +119,34 @@ public void setMinorVersion(int minorVersion) { public Method getMethod(String methodName, String paramAndReturnType){ + + for (Method m : methods) { + + int nameIndex = m.getNameIndex(); + int descriptorIndex= m.getDescriptorIndex(); + String name = ((UTF8Info)pool.getConstantInfo(nameIndex)).getValue(); + String desc = ((UTF8Info)pool.getConstantInfo(descriptorIndex)).getValue(); + if (name.equals(methodName) && desc.equals(paramAndReturnType)) { + return m; + } + } return null; } public Method getMainMethod(){ + for (Method m : methods) { + + int nameIndex = m.getNameIndex(); + int descriptorIndex= m.getDescriptorIndex(); + String name = ((UTF8Info)pool.getConstantInfo(nameIndex)).getValue(); + String desc = ((UTF8Info)pool.getConstantInfo(descriptorIndex)).getValue(); + if (name.equals("main") && desc.equals("([Ljava/lang/String;)V")) { + return m; + } + } + return null; } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java b/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java index 2bb36340f5..9a4be8a37a 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/CommandParser.java @@ -1,6 +1,7 @@ package com.coderising.jvm.cmd; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import com.coderising.jvm.clz.ClassFile; @@ -42,13 +43,106 @@ public class CommandParser { 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"); + + } + + List cmds = new ArrayList(); + codes = codes.toUpperCase(); + CommandIterator iter = new CommandIterator(codes); + + 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()); + + 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 (putfield.equals(opCode)) { + + PutFieldCmd cmd = new PutFieldCmd(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 (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"); + } + + calculateOffset(cmds); + + + } + + + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); - return null; + return result; } - private static void calcuateOffset(List cmds) { + private static void calculateOffset(List cmds) { int offset = 0; for (ByteCodeCommand cmd : cmds) { diff --git a/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java index 083bfe73f0..b6ddbad601 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class ClassInfo extends ConstantInfo { private int type = ConstantInfo.CLASS_INFO; private int utf8Index; @@ -26,4 +28,10 @@ public int getUtf8Index() { public void setUtf8Index(int utf8Index) { this.utf8Index = utf8Index; } + + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + } + } diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java index 5366000a7b..a2d0153f93 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public abstract class ConstantInfo { public static final int UTF8_INFO = 1; public static final int FLOAT_INFO = 4; @@ -29,4 +31,6 @@ public ConstantPool getConstantPool() { public abstract int getType(); + public abstract void accept(PrintVisitor visitor); + } diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java index 06b83239f4..40f95c7d77 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java @@ -21,8 +21,13 @@ public ConstantInfo getConstantInfo(int index) { //System.out.println(this.constantInfos.get(index)); return this.constantInfos.get(index); } + + public List getConstantInfos() { - public Object getSize() { + return constantInfos; + } + + public int getSize() { return this.constantInfos.size() - 1; } diff --git a/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java index 6161ac4c06..7e353c3009 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class FieldRefInfo extends ConstantInfo { private int type = ConstantInfo.FIELD_INFO; private int classInfoIndex; @@ -57,4 +59,9 @@ public String toString() { return getClassName() + " : " + typeInfo.getName() + ":" + typeInfo.getTypeInfo() + "]"; } + + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java index 1330036966..05882cd5f2 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class MethodRefInfo extends ConstantInfo { private int type = ConstantInfo.METHOD_INFO; @@ -55,5 +57,10 @@ public String toString() { return getClassName() + " : " + this.getMethodName() + " : " + this.getParamAndReturnType(); } + + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java index 9ce0725fd3..78dbe514b3 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class NameAndTypeInfo extends ConstantInfo { public int type = ConstantInfo.NAME_AND_TYPE_INFO; @@ -47,4 +49,9 @@ public void setIndex2(int index2) { public String toString() { return "(" + getName() + "," + getTypeInfo() + ")"; } + + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java b/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java index 7d1abf7699..a787901905 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class NullConstantInfo extends ConstantInfo { public NullConstantInfo() { @@ -11,4 +13,13 @@ public int getType() { return -1; } + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + + } + + + + } diff --git a/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java index e900b990cf..f713523450 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class StringInfo extends ConstantInfo { private int type = ConstantInfo.STRING_INFO; private int index; @@ -25,5 +27,11 @@ public void setIndex(int index) { public String toString() { return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java b/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java index b1179ad150..f0e548debf 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.print.PrintVisitor; + public class UTF8Info extends ConstantInfo { private int type = ConstantInfo.UTF8_INFO; private int length; @@ -35,4 +37,11 @@ public String toString() { return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + ")]"; } + @Override + public void accept(PrintVisitor visitor) { + visitor.visit(this); + + } + + } diff --git a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java index c20fbfe855..b9a2383303 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java @@ -37,7 +37,6 @@ public ClassFile parse(byte[] codes) { System.out.println("majorVersion is " + majorVersion); clzFile.setMajorVersion(majorVersion); - ConstantPool pool = parseConstantPool(iter); clzFile.setConstPool(pool); @@ -98,7 +97,7 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { // utf8-info UTF8Info utf8Info = new UTF8Info(pool); int length = iter.nextU2ToInt(); - System.out.println("length is " + length); + //System.out.println("length is " + length); utf8Info.setLength(length); byte[] bytes = iter.nextNbytesToHexString(length); String value = ""; @@ -107,7 +106,7 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { } catch (UnsupportedEncodingException e) { e.printStackTrace(); } - System.out.println("value is " + value); + //System.out.println("value is " + value); utf8Info.setValue(value); } else if (tag == 8) { diff --git a/group12/382266293/src/com/coderising/jvm/print/ClassFilePrinter.java b/group12/382266293/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..1f958aac6a --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.print; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.ClassFile; +import com.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.getMajorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "C:\\Users\\steve\\workspace\\coding2017n\\group12\\382266293\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = null; + try { + clzFile = loader.loadClass(className); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..be07ccd496 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,92 @@ +package com.coderising.jvm.print; + +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter implements PrintVisitor { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + + public void print(){ + + System.out.println("Constant Pool:"); + int size = pool.getSize(); + + for (int i = 1; i <= size; i++) { + ConstantInfo info = pool.getConstantInfo(i); + System.out.print("#" + i + " ="); + info.accept(this); + } + + } + + @Override + public void visit(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + } + + @Override + public void visit(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visit(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visit(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visit(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visit(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + + + @Override + public void visit(NullConstantInfo nullConstantInfo) { + + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/print/PrintVisitor.java b/group12/382266293/src/com/coderising/jvm/print/PrintVisitor.java new file mode 100644 index 0000000000..31aa70b955 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/print/PrintVisitor.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public interface PrintVisitor { + + void visit(ClassInfo pool); + void visit(FieldRefInfo info); + void visit(MethodRefInfo info); + void visit(NameAndTypeInfo info); + void visit(StringInfo info); + void visit(UTF8Info info); + void visit(NullConstantInfo nullConstantInfo); + +} From 7fbba66921c3761f6bf009a0d12abd15e1f9217a Mon Sep 17 00:00:00 2001 From: macvis_qq75939388 Date: Tue, 18 Apr 2017 13:14:04 +0800 Subject: [PATCH 056/151] =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/basic/dataStructure/ArrayList.java | 115 ++++++ .../java/basic/dataStructure/ArrayUtil.java | 245 +++++++++++++ .../basic/dataStructure/BinaryTreeNode.java | 58 +++ .../java/basic/dataStructure/LinkedList.java | 341 ++++++++++++++++++ .../main/java/basic/dataStructure/List.java | 12 + .../main/java/basic/dataStructure/Queue.java | 72 ++++ .../main/java/basic/dataStructure/Stack.java | 41 +++ .../java/basic/liteStruts/LoginAction.java | 39 ++ .../main/java/basic/liteStruts/ReadXML.java | 28 ++ .../main/java/basic/liteStruts/Struts.java | 78 ++++ .../src/main/java/basic/liteStruts/View.java | 23 ++ .../src/main/java/miniJVM/Demo.java | 7 + .../java/thread/download/DownloadThread.java | 39 ++ .../java/thread/download/FileDownloader.java | 106 ++++++ .../java/thread/download/api/Connection.java | 23 ++ .../download/api/ConnectionException.java | 8 + .../download/api/ConnectionManager.java | 10 + .../thread/download/api/DownloadListener.java | 5 + .../thread/download/impl/ConnectionImpl.java | 93 +++++ .../download/impl/ConnectionManagerImpl.java | 20 + .../java/data_structure/ArrayListTest.java | 69 ++++ .../java/data_structure/ArrayUtilTest.java | 67 ++++ .../data_structure/BinaryNodeTreeTest.java | 29 ++ .../java/data_structure/LinkedListTest.java | 151 ++++++++ .../test/java/data_structure/QueueTest.java | 50 +++ .../test/java/data_structure/StackTest.java | 49 +++ .../java/download/FileDownloaderTest.java | 54 +++ .../src/test/java/liteStruts/StrutsTest.java | 42 +++ 28 files changed, 1874 insertions(+) create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayUtil.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/List.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/liteStruts/LoginAction.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/liteStruts/ReadXML.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/liteStruts/Struts.java create mode 100644 group24/75939388/learning2017/src/main/java/basic/liteStruts/View.java create mode 100644 group24/75939388/learning2017/src/main/java/miniJVM/Demo.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/DownloadThread.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/FileDownloader.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/api/Connection.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionException.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionManager.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/api/DownloadListener.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionImpl.java create mode 100644 group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionManagerImpl.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/ArrayListTest.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java create mode 100644 group24/75939388/learning2017/src/test/java/data_structure/StackTest.java create mode 100644 group24/75939388/learning2017/src/test/java/download/FileDownloaderTest.java create mode 100644 group24/75939388/learning2017/src/test/java/liteStruts/StrutsTest.java diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java new file mode 100644 index 0000000000..8ae862da33 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java @@ -0,0 +1,115 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/2. + */ +public class ArrayList implements List { + private int size = 10; + //每次扩容的长度,默认为10 + private int extendSize = 10; + + private Object[] data = new Object[size]; + + public ArrayList(Object o) { + this.add(o); + } + + public ArrayList(){} + + public void add(Object o) { + if (this.size() == this.size) { + this.size += extendSize; + Object[] newData = new Object[this.size]; + System.arraycopy(this.data, 0, newData, 0, this.data.length); + this.data = newData; + } + + for (int i = 0; i < this.data.length; i++) { + if (data[i] == null) { + data[i] = o; + break; + } else continue; + } + } + + public void add(int index, Object o) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + if(this.size() == this.size){ + this.size += extendSize; + } + + Object[] newData = new Object[this.size]; + + System.arraycopy(this.data, 0, newData, 0, index); + newData[index] = o; + System.arraycopy(this.data, index, newData, index + 1, this.size() - index); + + this.data = newData; + } + + public Object get(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + for(int i = 0; i < this.size(); i ++){ + if(index == i){ + return this.data[i]; + } + } + + return null; + } + + public Object remove(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + + Object[] newData = new Object[this.size]; + Object removed = this.get(index); + + System.arraycopy(this.data, 0, newData, 0, index); + System.arraycopy(this.data, index + 1, newData, index, this.size() - index); + this.data = newData; + return removed; + } + + public int size() { + int size = 0; + for(Object obj : this.data){ + if(obj != null){ + size += 1; + } + } + + return size; + } + + public boolean contains(Object obj){ + for(int i = 0; i < this.size(); i++){ + if(obj == this.get(i)){ + return true; + } + } + + return false; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(Object obj : data){ + if(obj != null){ + sb.append(obj.toString()).append(","); + }else { +// sb.append("null,"); + continue; + } + } + + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayUtil.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayUtil.java new file mode 100644 index 0000000000..22bccaaf5b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayUtil.java @@ -0,0 +1,245 @@ +package basic.dataStructure; + +/** + * @author : 温友朝 + * @date : 2017/4/5 + */ +public class ArrayUtil { + /** + * 给定一个整形数组a , 对该数组的值进行置换 + * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * + * @param origin + * @return + */ + public void reverseArray(int[] origin) { + int length = origin.length; + int[] reversed = new int[length]; + for (int i = length - 1; i >= 0; i--) { + reversed[length - i - 1] = origin[i]; + } + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray) { + int length = oldArray.length; + int[] arr = new int[length]; + int index = 0; + for (int i = 0; i < length; i++) { + if (oldArray[i] != 0) { + arr[index] = oldArray[i]; + index++; + } + } + //非0的数据个数 + int[] newArr = new int[index]; + System.arraycopy(arr, 0, newArr, 0, index); + return newArr; + } + + public static Object[] remove(Object[] oldArray, Object value){ + int length = oldArray.length; + Object[] arr = new Object[length]; + int index = 0; + for (int i = 0; i < length; i++) { + if (oldArray[i] != value) { + arr[index] = oldArray[i]; + index++; + } + } + Object[] newArr = new Object[index]; + System.arraycopy(arr, 0, newArr, 0, index); + return newArr; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2) { + int length1 = array1.length; + int length2 = array2.length; + int[] arr = new int[length1 + length2]; + + System.arraycopy(array1, 0, arr, 0, length1); + System.arraycopy(array2, 0, arr, length1, length2); + + //去重 + for(int i = 0; i < arr.length; i++){ + for(int j = 0; j < arr.length; j++){ + if(i != j && arr[i] == arr[j]){ + arr[j] = 0; + } + } + } + + + int[] data = removeZero(arr); + int length = data.length; + + //排序 + for (int i = 0; i < length; i++) { + for(int j = 0; j < length; j++){ + if(data[i] < data[j]){ + int tmp = data[i]; + data[i] = data[j]; + data[j] = tmp; + } + } + } + return data; + } + + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * + * @param oldArray + * @param size + * @return + */ + public int[] grow(int[] oldArray, int size) { + int[] arr = new int[oldArray.length + size]; + System.arraycopy(oldArray, 0, arr, 0, oldArray.length); + return arr; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*) + * @param max + * @return + */ + public int[] fibonacci(int max) { + int[] empty = {}; + int[] arr2 = {1, 1}; + + switch (max){ + case 0 : return empty; + case 1 : return empty; + case 2 : return arr2; + default: { + int[] data = arr2; + int d = data[0] + data[1]; + while (d < max){ + int length = data.length; + d = data[length - 1] + data[length - 2]; + if(d > max){ + return data; + } + int[] temp = new int[data.length + 1]; + System.arraycopy(data, 0, temp, 0, length); + temp[length] = d; + + data = temp; + } + } + } + + return null; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public int[] getPrimes(int max) { + int[] data = new int[max]; + int index = 0; + for(int i = 1; i < max; i++){ + int divided = 0; + for(int j = i; j >= 1; j--){ + if(i % j == 0){ + divided++; + } + if(divided > 2){ + break; + }else if(j == 1 && divided == 2){ + data[index] = i; + index ++; + } + } + } + + int[] result = new int[index]; + System.arraycopy(data, 0, result, 0, index); + return result; + + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public int[] getPerfectNumbers(int max) { + int[] perfd = new int[max]; + int perfIndex = 0; + for(int i = 1; i <= max; i++){ + int index = 0; + int[] data = new int[i]; + for(int j = i - 1; j >= 1; j--){ + if(i % j == 0){ + data[index] = j; + index ++; + } + + if(j == 1 && getSum(data) == i){ + perfd[perfIndex] = i; + perfIndex++; + } + } + } + + return removeZero(perfd); + } + + private int getSum(int[] arr){ + int sum = 0; + for(int i : arr){ + sum += i; + } + return sum; + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * + * @param array + * @param seperator + * @return + */ + public String join(int[] array, String seperator) { + StringBuffer sb = new StringBuffer(); + for(int i : array){ + sb.append(i).append(seperator); + } + return sb.substring(0, sb.length() - 1).toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java new file mode 100644 index 0000000000..5050ae3c95 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java @@ -0,0 +1,58 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/4. + */ +public class BinaryTreeNode { + private int data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + private BinaryTreeNode(){} + + public BinaryTreeNode(int data){ + this.data = data; + this.left = null; + this.right = null; + } + + public void setData(int data){ + BinaryTreeNode node = new BinaryTreeNode(data); + if(compareTo(data)){ + if(this.left == null){ + this.left = node; + }else{ + this.left.setData(data); + } + }else{ + if(this.right == null){ + this.right = node; + }else{ + this.right.setData(data); + } + } + } + + public int getData(){ + return data; + } + + private boolean compareTo(int d) { + System.out.println("data=" + this.data + ", d=" + d); + return this.data > d; + } + + private StringBuffer dataStr = new StringBuffer(); + private int index = 0; +// public String toString(BinaryTreeNode node) { +// while (node.left != null || node.right != null){ +// dataStr.append(index + "层,数据=").append(node.data).append("|"); +// if(node.left != null){ +// dataStr.append(node.left.data) +// } +// index ++; +// } +// +// return dataStr.toString(); +// } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java new file mode 100644 index 0000000000..3ac85ad37b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java @@ -0,0 +1,341 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/3. + */ +public class LinkedList implements List { + private Node head; + + public LinkedList() { + this.head = new Node(); + } + + public void add(Object o) { + if (this.head.data == null) { + this.head = new Node(o, null); + } else { + Node temp = this.head; + while (temp.next != null) { + temp = temp.next; + } + temp.next = new Node(o, null); + } + } + + public void add(int index, Object o) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + if(index == 0){ + Node newNode = new Node(o, this.head); + this.head = newNode; + return; + } + + if(index == this.size()){ + this.add(o); + return; + } + + Node before = getNode(index - 1); + Node next = getNode(index); + Node newNode = new Node(o, next); + before.next = newNode; + + } + + private Node getNode(int index) { + int i = 0; + Node temp = this.head; + while (temp.data != null) { + if (index == i) { + return temp; + } + + if (temp.next != null) { + temp = temp.next; + } else break; + + i++; + } + + return null; + } + + public Object get(int index) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + return this.getNode(index).data; + } + + public Object remove(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + + Object removed = get(index); + + Node before = getNode(index - 1); + Node next = getNode(index + 1); + before.next = next; + + return removed; + } + + public int size() { + int size = 0; + Node temp = this.head; + while (temp.data != null) { + size++; + if (temp.next != null) { + temp = temp.next; + } else break; + } + + return size; + } + + public void asList(Object[] array){ + LinkedList list = new LinkedList(); + for(int i = 0; i < array.length; i++){ + list.add(array[i]); + } + + this.head = list.head; + } + + public Object[] toArray(LinkedList list){ + int size = list.size(); + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = list.get(i); + } + + return arr; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + Node temp = this.head; + while (temp.data != null) { + sb.append(temp.data.toString()).append(","); + if (temp.next != null) { + temp = temp.next; + } else break; + } + + return sb.toString(); + } + + private static class Node { + Object data; + Node next; + + public Node() {} + + public Node(Object obj, Node next) { + this.data = obj; + this.next = next; + } + + } + + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + int size = this.size(); + + if(size == 1){ + return; + } + + Object[] data = new Object[size]; + for(int i = 0; i < size; i++){ + data[i] = this.get(i); + } + + this.head = new Node(); + + for(int i = size - 1; i >= 0; i--){ + this.add(data[i]); + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int size = this.size(); + int index = this.size()/2; + ArrayList al = new ArrayList(); + for(int i = index; i < size; i++){ + al.add(this.get(i)); + } + + this.head = new Node(); + + for(int i = 0; i < al.size(); i++){ + this.add(al.get(i)); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + for(int j = i; j < i + length; j++){ + this.remove(i); + } + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + int size = list.size(); + int[] arr = new int[size]; + for(int i = 0; i < size; i++){ + int index = (Integer) list.get(i); + arr[i] = (Integer) this.get(index); + } + + return arr; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + Object[] arr1 = toArray(this); + Object[] arr2 = toArray(list); + for(int i = 0; i < arr2.length; i++){ + arr1 = ArrayUtil.remove(arr1, arr2[i]); + } + + asList(arr1); + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + int size = this.size(); + ArrayList indexList = new ArrayList(); + ArrayList valueList = new ArrayList(); + for(int i = 0; i < size; i ++){ + int valueI = (Integer)this.get(i); + int index = 0; + for(int j = i + 1; j < size; j++){ + if(valueList.contains(valueI)){ + continue; + } + int valueJ = (Integer) this.get(j); + if(valueJ == valueI){ + index++; + } + + if(index > 0){ + indexList.add(j); + valueList.add(valueJ); + } + } + } + + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = indexList.contains(i) ? false : this.get(i); + } + + ArrayUtil au = new ArrayUtil(); + arr = au.remove(arr, false); + + asList(arr); + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + int size = this.size(); + int[] range = new int[max - min]; + int index = 0; + for(int i = 0; i < size; i++){ + int value = (Integer) this.get(i); + if(value > min && value < max){ + range[index] = value; + index++; + } + } + + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = this.get(i); + } + + for(int i = 0; i < range.length; i++){ + arr = ArrayUtil.remove(arr, range[i]); + } + + asList(arr); + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + //组合成新的链表 + int listSize = list.size(); + for(int i = 0 ; i < listSize; i ++){ + this.add(list.get(i)); + } + + //转化成数组 + int size = this.size(); + int[] arr = new int[size]; + for(int i = 0; i < size; i++){ + arr[i] = (Integer)this.get(i); + } + //排序 + for(int i = 0; i < size - 1; i ++){ + for(int j = 0; j < size - i - 1; j ++){ + if(arr[j] >= arr[j + 1]){ + int temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } + + //组装 + LinkedList li = new LinkedList(); + for(int i = 0; i < size; i ++){ + li.add(arr[i]); + } + return li; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/List.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/List.java new file mode 100644 index 0000000000..dc2a62aab3 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/List.java @@ -0,0 +1,12 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/2. + */ +public interface List { + void add(Object o); + void add(int index, Object o); + Object get(int index); + Object remove(int index); + int size(); +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java new file mode 100644 index 0000000000..36ca7e9647 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java @@ -0,0 +1,72 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/4. + */ +public class Queue { + private Object[] data; + + private int size = 10; + + private int extendedSize = 10; + + public Queue(){ + this.data = new Object[size]; + } + + public Queue(Object o){ + this.data = new Object[size]; + data[0] = o; + } + + public void enQueue(Object o){ + //被添加的位置 + int index = this.size(); + if(this.size() == this.size){ + this.size += extendedSize; + Object[] newData = new Object[this.size]; + System.arraycopy(this.data, 0, newData, 0, index); + newData[index] = o; + this.data = newData; + }else{ + this.data[index] = o; + } + } + + public Object deQueue(){ + Object[] newData = new Object[this.size]; + Object d = this.data[0]; + System.arraycopy(this.data, 1, newData, 0, this.size - 1); + this.data = newData; + + return d; + } + + public Object peek(){ + return this.data[0]; + } + + public boolean isEmpty(){ + return peek() == null; + } + + public int size(){ + int size = 0; + for(Object obj : this.data){ + size += obj == null ? 0 : 1; + } + + return size; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(Object obj : this.data){ + if(obj != null){ + sb.append(obj.toString()).append(","); + }else break; + } + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java new file mode 100644 index 0000000000..bea16033fa --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java @@ -0,0 +1,41 @@ +package basic.dataStructure; + +/** + * Created by macvi on 2017/4/4. + */ +public class Stack { + + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + this.elementData.add(o); + } + + public Object pop(){ + int index = elementData.size() - 1; + Object obj = elementData.remove(index); + + return obj; + } + + public Object peek(){ + int index = elementData.size() - 1; + return elementData.get(index); + } + public boolean isEmpty(){ + return peek() == null; + } + public int size(){ + return elementData.size(); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(int i = this.size() - 1; i >= 0; i--){ + sb.append(elementData.get(i).toString()).append(","); + } + + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/liteStruts/LoginAction.java b/group24/75939388/learning2017/src/main/java/basic/liteStruts/LoginAction.java new file mode 100644 index 0000000000..14b8aba8e2 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/liteStruts/LoginAction.java @@ -0,0 +1,39 @@ +package basic.liteStruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/liteStruts/ReadXML.java b/group24/75939388/learning2017/src/main/java/basic/liteStruts/ReadXML.java new file mode 100644 index 0000000000..458b247e18 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/liteStruts/ReadXML.java @@ -0,0 +1,28 @@ +package basic.liteStruts; + +import org.dom4j.Document; +import org.dom4j.io.SAXReader; + +import java.io.File; + +/** + * @author : 温友朝 + * @date : 2017/4/10 + */ +public class ReadXML { + Document document; + + public ReadXML(String filePath) throws Exception{ + SAXReader reader = new SAXReader(); + document = reader.read(new File(ReadXML.class.getResource("/").getFile()) + filePath); + } + + public String getActionClass(String actionName){ + return document.selectSingleNode("//action[@name='" + actionName + "']").valueOf("@class"); + } + + public String getJspPage(String actionName, String result){ + return document.selectSingleNode("//action[@name='" + actionName + "']") + .selectSingleNode("//result[@name='" + result + "']").getText(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/liteStruts/Struts.java b/group24/75939388/learning2017/src/main/java/basic/liteStruts/Struts.java new file mode 100644 index 0000000000..3b28f2bf60 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/liteStruts/Struts.java @@ -0,0 +1,78 @@ +package basic.liteStruts; + +import java.lang.reflect.Method; +import java.util.Map; + + +public class Struts { + /** + * 0. 读取配置文件struts.xml + *

+ * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + * ("name"="test" , "password"="1234") , + * 那就应该调用 setName和setPassword方法 + *

+ * 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + *

+ * 3. 通过反射找到对象的所有getter方法(例如 getMessage), + * 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + * 放到View对象的parameters + *

+ * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + * 放到View对象的jsp字段中。 + */ + public static View runAction(String actionName, Map parameters) { + try{ + //0. 读取配置文件struts.xml + ReadXML read = new ReadXML("/resources/struts.xml"); + //1. 找到对应的class + String className = read.getActionClass(actionName); + Class clz = Class.forName(className); + //得到对象 + Object la = clz.newInstance(); + setNameAndPassword(clz, la, parameters); + //2. 调用execute方法 + String result = invokeExecute(clz, la); + //3. 找到对象的所有getter方法 + getResultMap(clz, la, parameters); + //4. 确定使用哪一个jsp + String viewName = read.getJspPage(actionName, result); + View view = new View(); + view.setJsp(viewName); + view.setParameters(parameters); + return view; + }catch(Exception e){ + e.printStackTrace(); + return null; + } + } + + private static void setNameAndPassword(Class clz, Object la, Map parameters) throws Exception { + Method setName = clz.getDeclaredMethod("setName", String.class); + setName.invoke(la, parameters.get("name")); + + Method setPassword = clz.getDeclaredMethod("setPassword", String.class); + setPassword.invoke(la, parameters.get("password")); + } + + private static String invokeExecute(Class clz, Object la)throws Exception{ + Method execute = clz.getDeclaredMethod("execute", null); + Method getMessage = clz.getDeclaredMethod("getMessage", null); + execute.invoke(la, null); + return getMessage.invoke(la, null).toString(); + } + + private static void getResultMap(Class clz, Object la, Map parameters) throws Exception{ + Method[] methods = clz.getMethods(); + for(Method me : methods){ + if(me.getName().startsWith("get")){ + String info = me.invoke(la, null).toString(); + String method= me.getName(); + String key = method.substring(3, method.length()).toLowerCase(); + parameters.put(key, info); + }else continue; + } + + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/liteStruts/View.java b/group24/75939388/learning2017/src/main/java/basic/liteStruts/View.java new file mode 100644 index 0000000000..777380b8f9 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/liteStruts/View.java @@ -0,0 +1,23 @@ +package basic.liteStruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java b/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java new file mode 100644 index 0000000000..565983ab06 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java @@ -0,0 +1,7 @@ +package miniJVM; + +/** + * Created by macvi on 2017/4/11. + */ +public class Demo { +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/DownloadThread.java b/group24/75939388/learning2017/src/main/java/thread/download/DownloadThread.java new file mode 100644 index 0000000000..190cae6423 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/DownloadThread.java @@ -0,0 +1,39 @@ +package thread.download; + + +import thread.download.api.Connection; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + String localFile = ""; + + CyclicBarrier barrier; + + public DownloadThread(Connection conn, int startPos, int endPos, String localFileName, CyclicBarrier barrier){ + this.localFile = localFileName; + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.barrier = barrier; + } + public void run(){ + try{ + RandomAccessFile file = new RandomAccessFile(localFile, "rw"); + byte[] buffer = this.conn.read(this.startPos, this.endPos); + file.seek(startPos); + file.write(buffer); + file.close(); + this.conn.close(); + barrier.await(); + }catch(Exception e){ + e.printStackTrace(); + } + } +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/FileDownloader.java b/group24/75939388/learning2017/src/main/java/thread/download/FileDownloader.java new file mode 100644 index 0000000000..f50560b8be --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/FileDownloader.java @@ -0,0 +1,106 @@ +package thread.download; + +import thread.download.api.Connection; +import thread.download.api.ConnectionManager; +import thread.download.api.DownloadListener; + +import java.io.File; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class FileDownloader { + + String url; + String fileLocation; + DownloadListener listener; + ConnectionManager cm; + + RandomAccessFile file; + + int length; + + private static final int MAX_THREAD_NUM = 5; + + + public FileDownloader(String _url, String fileLocation) { + this.url = _url; + this.fileLocation = fileLocation; + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + + try { + CyclicBarrier barrier = new CyclicBarrier(MAX_THREAD_NUM, new Runnable() { + public void run() { + listener.notifyFinished(); + } + }); + + conn = cm.open(this.url); + this.length = conn.getContentLength(); + + file = getEmptyFile(); + + int divided = length/MAX_THREAD_NUM; + int[] pos = new int[MAX_THREAD_NUM + 1]; + for(int i = 0; i < MAX_THREAD_NUM; i++){ + pos[i] = i == 0 ? 0 : divided * i; + } + pos[MAX_THREAD_NUM] = length; + + for(int i = 0; i < MAX_THREAD_NUM; i++){ + new DownloadThread(conn, pos[i], pos[i + 1] - 1, this.fileLocation, barrier).start(); + } + + + File file2 = new File(fileLocation); + System.out.println("file.length=" + file2.length()); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + } + + public RandomAccessFile getEmptyFile(){ + try{ + RandomAccessFile file = new RandomAccessFile(this.fileLocation, "rw"); + byte[] empty = new byte[this.length]; + file.write(empty); + file.close(); + return file; + }catch(Exception e){ + e.printStackTrace(); + } + return null; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/api/Connection.java b/group24/75939388/learning2017/src/main/java/thread/download/api/Connection.java new file mode 100644 index 0000000000..08a85b35dd --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/api/Connection.java @@ -0,0 +1,23 @@ +package thread.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionException.java b/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionException.java new file mode 100644 index 0000000000..e8fac91d1e --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionException.java @@ -0,0 +1,8 @@ +package thread.download.api; + +public class ConnectionException extends Exception { + + public ConnectionException(String msg){ + super(msg); + } +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionManager.java b/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionManager.java new file mode 100644 index 0000000000..f5f6c2ff70 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package thread.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + Connection open(String url) throws ConnectionException; +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/api/DownloadListener.java b/group24/75939388/learning2017/src/main/java/thread/download/api/DownloadListener.java new file mode 100644 index 0000000000..16393c4dd9 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package thread.download.api; + +public interface DownloadListener { + void notifyFinished(); +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionImpl.java b/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..2e2544ab27 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionImpl.java @@ -0,0 +1,93 @@ +package thread.download.impl; + +import thread.download.api.Connection; +import thread.download.api.ConnectionException; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class ConnectionImpl implements Connection { + + private int length = 0; + + private URL url; + + private HttpURLConnection conn; + + private InputStream is; + + private ByteArrayOutputStream baos; + + private ConnectionImpl() {} + + public ConnectionImpl(URL url) { + this.url = url; + try { + this.conn = (HttpURLConnection) url.openConnection(); + this.conn.setRequestMethod("GET"); + this.conn.setReadTimeout(5000); + int responseCode = this.conn.getResponseCode(); + System.out.println("连接状态=" + responseCode); + if (responseCode != 200) { + throw new ConnectionException("连接到" + url.toURI() + "失败"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public byte[] read(int startPos, int endPos) throws IOException { + try { + //设置读取段落 + this.conn = (HttpURLConnection) url.openConnection(); + this.conn.setRequestMethod("GET"); + this.conn.setReadTimeout(5000); + this.conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + //获取返回值 + int response = conn.getResponseCode(); + if(response != 200 && response != 206){ + throw new ConnectException("没有连接上" + url.toURI() + ", 状态码为" + response); + } + //开始读取 + int length = endPos - startPos + 1; + this.is = conn.getInputStream(); + byte[] buffer = new byte[1024]; + baos = new ByteArrayOutputStream(length); + while(-1 != is.read(buffer)){ + baos.write(buffer); + } + System.out.println(startPos + "-" + endPos + "文件段读取完成"); + return baos.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + this.close(); + } + } + + public int getContentLength() { + try { + this.length = this.conn.getContentLength(); + System.out.println("获取的文件长度=" + length); + return this.length; + } catch (Exception e) { + e.printStackTrace(); + return -1; + } + } + + public void close() { + try { + if(is != null){ + is.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionManagerImpl.java b/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..ede8ccac00 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/thread/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,20 @@ +package thread.download.impl; + +import thread.download.api.Connection; +import thread.download.api.ConnectionException; +import thread.download.api.ConnectionManager; + +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + public Connection open(String url) throws ConnectionException { + Connection conn = null; + try{ + conn = new ConnectionImpl(new URL(url)); + }catch(Exception e){ + e.printStackTrace(); + } + return conn; + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/ArrayListTest.java b/group24/75939388/learning2017/src/test/java/data_structure/ArrayListTest.java new file mode 100644 index 0000000000..ee8ee6b0d0 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/ArrayListTest.java @@ -0,0 +1,69 @@ +package data_structure; + +import org.junit.Test; +import basic.dataStructure.ArrayList; + +/** + * Created by macvi on 2017/4/2. + */ +public class ArrayListTest { + + @Test + public void TestAdd(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 32; i++){ + al.add(i + ""); + } + + System.out.println("ArrayList.content-->" + al.toString()); + } + + + @Test + public void testIndexAdd(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 17; i ++){ + al.add(i + ""); + } + + al.add(3, "xxoo"); + al.add(11, "abcd"); + al.add(0, "efgh"); + al.add(al.size(), "ijkl"); + + System.out.println("al.toString-->" + al.toString()); + System.out.println("size-->" + al.size()); + } + + @Test + public void testGet(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 18; i ++){ + al.add(i + "zxcd"); + } + + System.out.println("get-->" + al.get(13)); + } + + @Test + public void testRemove(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 18; i ++){ + al.add(i + ""); + } + System.out.println("size1-->" + al.size()); + System.out.println("al.toString1-->" + al.toString()); + String re = (String)al.remove(12); + System.out.println("remove index=12 :"); + System.out.println("re-->" + re); + System.out.println("size2-->" + al.size()); + System.out.println("al.toString2-->" + al.toString()); + + String re1 = (String)al.remove(1); + System.out.println("remove index=1 :"); + System.out.println("re-->" + re1); + System.out.println("size2-->" + al.size()); + System.out.println("al.toString2-->" + al.toString()); + } + +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java b/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java new file mode 100644 index 0000000000..1dc1a6f263 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java @@ -0,0 +1,67 @@ +package data_structure; + +import org.junit.Test; +import basic.dataStructure.ArrayUtil; + +import java.util.Arrays; + +/** + * @author : 温友朝 + * @date : 2017/4/5 + */ +public class ArrayUtilTest { + ArrayUtil au = new ArrayUtil(); + + @Test + public void testReverse(){ + int[] arr = {1, 2, 3, 4, 5}; + this.au.reverseArray(arr); + } + + @Test + public void testTrim(){ + int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; + int[] arr = this.au.removeZero(oldArr); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testMerge(){ + int[] a1 = {3, 5, 7,8}; + int[] a2 = {4, 5, 6,7}; + + int[] arr = this.au.merge(a1, a2); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testGrow(){ + int[] arr = {1, 2, 3, 4, 5}; + int[] arr2 = this.au.grow(arr, 4); + System.out.println(Arrays.toString(arr2)); + } + + @Test + public void testFibonacci(){ + int[] arr = this.au.fibonacci(100); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testPrimes(){ + int[] arr = this.au.getPrimes(100000); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testPerfectNumbers(){ + int[] arr = this.au.getPerfectNumbers(10000); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testJoin(){ + int[] arr = this.au.getPerfectNumbers(10000); + System.out.println(this.au.join(arr, "-")); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java b/group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java new file mode 100644 index 0000000000..df976147e3 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java @@ -0,0 +1,29 @@ +package data_structure; + +import org.junit.Test; +import basic.dataStructure.BinaryTreeNode; + +/** + * @author : 温友朝 + * @date : 2017/4/5 + */ +public class BinaryNodeTreeTest { + +// @Test +// public BinaryTreeNode getTree(){ +// BinaryTreeNode btn = new BinaryTreeNode(5); +// btn.setData(3); +// +// return btn; +// } + + @Test + public void testAdd(){ + BinaryTreeNode btn = new BinaryTreeNode(5); + btn.setData(3); + btn.setData(7); + btn.setData(10); + btn.setData(6); + btn.setData(4); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java b/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java new file mode 100644 index 0000000000..c98a305623 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java @@ -0,0 +1,151 @@ +package data_structure; + +import basic.dataStructure.LinkedList; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +/** + * Created by macvi on 2017/4/3. + */ +public class LinkedListTest { + + LinkedList ll = new LinkedList(); + + @Before + public void init(){ + for(int i = 0; i < 10; i++){ + ll.add(i); + } + } + + @After + public void print(){ + + } + + + @Test + public void testLinkedListAdd(){ + LinkedList ll = new LinkedList(); + ll.add("123"); + ll.add("456"); + ll.add("asdf"); + ll.add("zxcv"); + + + System.out.println("ll.toString-->" + ll); + System.out.println("ll.size--->" + ll.size()); + } + + @Test + public void testLinkedListIndexAdd(){ + System.out.println("12345"); + } + + @Test + public void testGet(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 10; i ++){ + ll.add(i + ""); + } + + System.out.println("get-->" + ll.get(9)); + System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); + } + + @Test + public void testIndexAdd(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 5; i ++){ + ll.add(i + ""); + } + + ll.add(5, "xxoo"); + System.out.println("index get-->" + ll.get(0)); + System.out.println("ll.toString2-->" + ll.toString() + "\nsize-->" + ll.size()); + } + + @Test + public void testRemove(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 6; i ++){ + ll.add(i + ""); + } + + Object removed = ll.remove(-1); + System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); + System.out.println("removed-->" + removed.toString()); + } + + @Test + public void testReverse(){ + ll.reverse(); + System.out.println("ll.reverse-->" + ll.toString()); + } + + @Test + public void testRemoveFirstHalf(){ + ll.removeFirstHalf(); + System.out.println("ll.removeFirstHalf-->" + ll.toString()); + } + + @Test + public void testRemoveL(){ + ll.remove(2, 5); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testGetElements(){ + LinkedList l2 = new LinkedList(); + l2.add(3); + l2.add(5); + l2.add(9); + l2.add(0); + + int[] arr = ll.getElements(l2); + System.out.println("arr->" + Arrays.toString(arr)); + } + + @Test + public void testRemoveDuplicate(){ + ll.add(1); + ll.add(3); + ll.add(4); + ll.add(10); + ll.add(11); + ll.removeDuplicateValues(); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testRemoveRange(){ + ll.removeRange(2, 6); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testSubtract(){ + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(5); + + ll.subtract(list); + System.out.println("ll.toString-->" + ll); + } + + @Test + public void testIntersection(){ + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(5); + + LinkedList list2 = ll.intersection(list); + System.out.println(list2); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java b/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java new file mode 100644 index 0000000000..3db6d82e49 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java @@ -0,0 +1,50 @@ +package data_structure; + +import org.junit.Assert; +import org.junit.Test; +import basic.dataStructure.Queue; + +/** + * Created by macvi on 2017/4/4. + */ +public class QueueTest { + + private Queue newQueue(){ + Queue q = new Queue(); + for(int i = 0; i < 13; i++){ + q.enQueue(i + ""); + } + + return q; + } + + @Test + public void testEnqueue(){ + Queue q = newQueue(); + q.enQueue(10 + ""); + q.enQueue( "xxoo"); + System.out.println("queue-->" + q.toString()); + } + + @Test + public void testSize(){ + Queue q = newQueue(); + + Assert.assertEquals(13, q.size()); + } + + @Test + public void testDequeue(){ + Queue q = newQueue(); + Object obj = q.deQueue(); + + Assert.assertEquals("0", obj); + } + + @Test + public void testIsEmpty(){ + Queue q = newQueue(); + + Assert.assertEquals(false, q.isEmpty()); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java b/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java new file mode 100644 index 0000000000..b933b8b63e --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java @@ -0,0 +1,49 @@ +package data_structure; + +import org.junit.Assert; +import org.junit.Test; +import basic.dataStructure.Stack; + +/** + * Created by macvi on 2017/4/4. + */ +public class StackTest { + + private Stack getStack(){ + Stack s = new Stack(); + for(int i = 0; i < 14; i ++){ + s.push(i + ""); + } + + return s; + } + + @Test + public void pushTest(){ + Stack s = getStack(); + + System.out.println("stack-->" + s.toString()); + } + + @Test + public void testSize(){ + Stack s = getStack(); + + Assert.assertEquals(14, s.size()); + } + + @Test + public void testPeek(){ + Stack s = getStack(); + + Assert.assertEquals("13", s.peek()); + } + + @Test + public void testPop(){ + Stack s = getStack(); + + Assert.assertEquals("13", s.pop()); + Assert.assertEquals(13, s.size()); + } +} diff --git a/group24/75939388/learning2017/src/test/java/download/FileDownloaderTest.java b/group24/75939388/learning2017/src/test/java/download/FileDownloaderTest.java new file mode 100644 index 0000000000..0dc8536269 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/download/FileDownloaderTest.java @@ -0,0 +1,54 @@ +package download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import thread.download.FileDownloader; +import thread.download.api.ConnectionManager; +import thread.download.api.DownloadListener; +import thread.download.impl.ConnectionManagerImpl; + + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "https://www.baidu.com/img/bd_logo1.png"; + String fileLocation = "D:\\Tee\\JavaLearnin\\test.png"; + FileDownloader downloader = new FileDownloader(url, fileLocation); + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + public void notifyFinished() { + downloadFinished = true; + } + + }); + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + } + +} diff --git a/group24/75939388/learning2017/src/test/java/liteStruts/StrutsTest.java b/group24/75939388/learning2017/src/test/java/liteStruts/StrutsTest.java new file mode 100644 index 0000000000..4477c5f51b --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/liteStruts/StrutsTest.java @@ -0,0 +1,42 @@ +package liteStruts; + +import org.junit.Assert; +import org.junit.Test; +import basic.liteStruts.Struts; +import basic.liteStruts.View; + +import java.util.HashMap; +import java.util.Map; + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} From 9512e534cb2eb05e0f86a0ee7e64ba2579e0e6e7 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 18 Apr 2017 15:35:34 +0800 Subject: [PATCH 057/151] 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 814cb2789e976b4a4973d0e83d8c71fadf6bbd3b Mon Sep 17 00:00:00 2001 From: gongxun Date: Tue, 18 Apr 2017 19:05:12 +0800 Subject: [PATCH 058/151] =?UTF-8?q?=E6=9A=82=E5=AD=98=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.16/cmd/BiPushCmd.java | 2 +- .../785396327/4.16/cmd/ByteCodeCommand.java | 2 +- group17/785396327/4.16/cmd/CommandParser.java | 81 ++++++++++++++++++- group17/785396327/4.16/cmd/GetFieldCmd.java | 2 +- .../4.5/test/ClassFileloaderTest.java | 60 +++++++------- 5 files changed, 113 insertions(+), 34 deletions(-) diff --git a/group17/785396327/4.16/cmd/BiPushCmd.java b/group17/785396327/4.16/cmd/BiPushCmd.java index e69c53310f..9353ea0412 100644 --- a/group17/785396327/4.16/cmd/BiPushCmd.java +++ b/group17/785396327/4.16/cmd/BiPushCmd.java @@ -4,7 +4,7 @@ import constant.ConstantPool; /** - * Created by IBM on 2017/4/17. + * Created by william on 2017/4/17. */ public class BiPushCmd extends OneOperandCmd { public BiPushCmd(ClassFile clzFile, String opCode) { diff --git a/group17/785396327/4.16/cmd/ByteCodeCommand.java b/group17/785396327/4.16/cmd/ByteCodeCommand.java index 97865bbd31..f10bfa21d3 100644 --- a/group17/785396327/4.16/cmd/ByteCodeCommand.java +++ b/group17/785396327/4.16/cmd/ByteCodeCommand.java @@ -8,7 +8,7 @@ import java.util.Map; /** - * Created by IBM on 2017/4/17. + * Created by william on 2017/4/17. */ public abstract class ByteCodeCommand { String opCode; diff --git a/group17/785396327/4.16/cmd/CommandParser.java b/group17/785396327/4.16/cmd/CommandParser.java index 35d9f80831..5f5956350d 100644 --- a/group17/785396327/4.16/cmd/CommandParser.java +++ b/group17/785396327/4.16/cmd/CommandParser.java @@ -1,11 +1,12 @@ package cmd; import clz.ClassFile; +import constant.ClassInfo; import java.util.List; /** - * Created by IBM on 2017/4/17. + * Created by william on 2017/4/17. */ public class CommandParser { public static final String aconst_null = "01"; @@ -44,8 +45,81 @@ public class CommandParser { public static final String iinc = "84"; public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + CommandIterator commandIterator = new CommandIterator(codes); + String command = commandIterator.next2CharAsString().toUpperCase(); + if (command.equals(aconst_null)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(1); + } else if (command.equals(new_object)) { + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, command); + int oprand1 = commandIterator.next2CharAsInt(); + int oprand2 = commandIterator.next2CharAsInt(); + newObjectCmd.setOprand1(oprand1); + newObjectCmd.setOprand2(oprand2); + } else if (command.equals(lstore)) { + } else if (command.equals(invokespecial)) { + + } else if (command.equals(invokevirtual)) { + + } else if (command.equals(getfield)) { + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, command); + } else if (command.equals(putfield)) { + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, command); + } else if (command.equals(getstatic)) { + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, command); + } else if (command.equals(ldc)) { + LdcCmd ldcCmd = new LdcCmd(clzFile, command); + } else if (command.equals(dup)) { + + } else if (command.equals(bipush)) { + BiPushCmd biPushCmd = new BiPushCmd(clzFile, command); + } else if (command.equals(aload_0)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + } else if (command.equals(aload_1)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + } else if (command.equals(aload_2)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + } else if (command.equals(iload)) { + + } else if (command.equals(iload_2)) { + + } else if (command.equals(iload_1)) { + + } else if (command.equals(iload_3)) { + + } else if (command.equals(fload_3)) { + + } else if (command.equals(voidreturn)) { + + } else if (command.equals(ireturn)) { + + } else if (command.equals(freturn)) { + + } else if (command.equals(astore_1)) { + + } else if (command.equals(if_icmp_ge)) { + + } else if (command.equals(if_icmple)) { + + } else if (command.equals(goto_no_condition)) { + + } else if (command.equals(iconst_0)) { + + } else if (command.equals(iconst_1)) { + + } else if (command.equals(istore_1)) { + + } else if (command.equals(istore_2)) { + + } else if (command.equals(iadd)) { + + } else if (command.equals(iinc)) { + + } else { + throw new RuntimeException("wrong command : " + command); + } return null; } @@ -71,6 +145,11 @@ public boolean hasNext() { return pos < this.codes.length(); } + /** + * 从字符串中截取前两个字符 + * + * @return + */ public String next2CharAsString() { String result = codes.substring(pos, pos + 2); pos += 2; diff --git a/group17/785396327/4.16/cmd/GetFieldCmd.java b/group17/785396327/4.16/cmd/GetFieldCmd.java index a255cef97b..c7307abf56 100644 --- a/group17/785396327/4.16/cmd/GetFieldCmd.java +++ b/group17/785396327/4.16/cmd/GetFieldCmd.java @@ -4,7 +4,7 @@ import constant.ConstantPool; /** - * Created by IBM on 2017/4/17. + * Created by william on 2017/4/17. */ public class GetFieldCmd extends TwoOperandCmd { public GetFieldCmd(ClassFile clzFile,String opCode) { diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 3e4f3e100c..2a8badce36 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -228,36 +228,36 @@ public void testMethods(){ "2ab700012a2bb500022a1cb50003b1"); } - { - Method m = methods.get(1); - assertMethodEquals(pool,m, - "setName", - "(Ljava/lang/String;)V", - "2a2bb50002b1"); - - } - { - Method m = methods.get(2); - assertMethodEquals(pool,m, - "setAge", - "(I)V", - "2a1bb50003b1"); - } - { - Method m = methods.get(3); - assertMethodEquals(pool,m, - "sayHello", - "()V", - "b200041205b60006b1"); - - } - { - Method m = methods.get(4); - assertMethodEquals(pool,m, - "main", - "([Ljava/lang/String;)V", - "bb0007591208101db700094c2bb6000ab1"); - } +// { +// Method m = methods.get(1); +// assertMethodEquals(pool,m, +// "setName", +// "(Ljava/lang/String;)V", +// "2a2bb50002b1"); +// +// } +// { +// Method m = methods.get(2); +// assertMethodEquals(pool,m, +// "setAge", +// "(I)V", +// "2a1bb50003b1"); +// } +// { +// Method m = methods.get(3); +// assertMethodEquals(pool,m, +// "sayHello", +// "()V", +// "b200041205b60006b1"); +// +// } +// { +// Method m = methods.get(4); +// assertMethodEquals(pool,m, +// "main", +// "([Ljava/lang/String;)V", +// "bb0007591208101db700094c2bb6000ab1"); +// } } private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ From dca236eb2b7752ecdd3e8f14c6e3dcca28d3ce24 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Tue, 18 Apr 2017 19:50:06 +0800 Subject: [PATCH 059/151] Infix Postfix Prefix finished --- .../donaldy/basic/expr/InfixToPostfix.java | 59 ++++++++++++++++ .../basic/expr/InfixToPostfixTest.java | 22 ++++++ .../com/donaldy/basic/expr/PostfixExpr.java | 67 ++++++++++++++++++ .../donaldy/basic/expr/PostfixExprTest.java | 41 +++++++++++ .../com/donaldy/basic/expr/PrefixExpr.java | 69 +++++++++++++++++++ .../donaldy/basic/expr/PrefixExprTest.java | 45 ++++++++++++ .../src/com/donaldy/basic/expr/Token.java | 50 ++++++++++++++ .../com/donaldy/basic/expr/TokenParser.java | 57 +++++++++++++++ .../donaldy/basic/expr/TokenParserTest.java | 41 +++++++++++ 9 files changed, 451 insertions(+) create mode 100644 group24/448641125/src/com/donaldy/basic/expr/InfixToPostfix.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/InfixToPostfixTest.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/PostfixExpr.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/PostfixExprTest.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/PrefixExpr.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/PrefixExprTest.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/Token.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/TokenParser.java create mode 100644 group24/448641125/src/com/donaldy/basic/expr/TokenParserTest.java diff --git a/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfix.java b/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfix.java new file mode 100644 index 0000000000..54666845de --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfix.java @@ -0,0 +1,59 @@ +package com.donaldy.basic.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + + Stack opStack = new Stack<>(); + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + List newTokens = new ArrayList<>(); + + for (Token token : tokens) { + + if (token.isOperator()) { + + while (true) { + if (opStack.isEmpty()) { + opStack.push(token); + + break; + } + + if (token.hasHigherPriority(opStack.peek())) { + + opStack.push(token); + + break; + } + + newTokens.add(opStack.pop()); + + } + + + } + + if (token.isNumber()) { + newTokens.add(token); + } + + } + + while (!opStack.isEmpty()) { + newTokens.add(opStack.pop()); + } + + + return newTokens; + } + + + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfixTest.java b/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..f6dda0ee18 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/InfixToPostfixTest.java @@ -0,0 +1,22 @@ +package com.donaldy.basic.expr; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/4/18. + */ +public class InfixToPostfixTest { + + @Test + public void test() { + + String expr = "9 + 3-1 *3+10/2"; + //Assert.assertEquals("9 3 1-3*+ 10 2/+", InfixToPostfix.convert(expr)); + + expr = "10-2*3+50"; + Assert.assertEquals("[10, 2, 3, *, -, 50, +]", InfixToPostfix.convert(expr).toString()); + + } + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/PostfixExpr.java b/group24/448641125/src/com/donaldy/basic/expr/PostfixExpr.java new file mode 100644 index 0000000000..ec175d192c --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/PostfixExpr.java @@ -0,0 +1,67 @@ +package com.donaldy.basic.expr; + + +import java.util.List; +import java.util.Stack; + +/** + * 从左到右遍历, + * 1. 若为数字,则入栈 + * 2. 若为运算符,则calculate + */ +public class PostfixExpr { + + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack numStack = new Stack<>(); + + + for(Token token : tokens){ + + if (token.isOperator()){ + + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); + + } + + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + + 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"); + } + + + + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/PostfixExprTest.java b/group24/448641125/src/com/donaldy/basic/expr/PostfixExprTest.java new file mode 100644 index 0000000000..3195c7b3b2 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.donaldy.basic.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/group24/448641125/src/com/donaldy/basic/expr/PrefixExpr.java b/group24/448641125/src/com/donaldy/basic/expr/PrefixExpr.java new file mode 100644 index 0000000000..aaee04d871 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/PrefixExpr.java @@ -0,0 +1,69 @@ +package com.donaldy.basic.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 从右到左遍历 + * 1. 若为数字,则入栈 + * 2. 若为符号,则calculate + */ +public class PrefixExpr { + + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack numStack = new Stack<>(); + Stack opStack = new Stack<>(); + + for(int i = tokens.size() - 1; i >= 0 ; --i){ + Token token = tokens.get(i); + + if (token.isOperator()){ + opStack.push(token.toString()); + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(opStack.pop(), f1,f2)); + } + + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while (!opStack.isEmpty()) { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(opStack.pop(), 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"); + } + + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/PrefixExprTest.java b/group24/448641125/src/com/donaldy/basic/expr/PrefixExprTest.java new file mode 100644 index 0000000000..435a82d8b1 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.donaldy.basic.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/group24/448641125/src/com/donaldy/basic/expr/Token.java b/group24/448641125/src/com/donaldy/basic/expr/Token.java new file mode 100644 index 0000000000..db639bcbcf --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/Token.java @@ -0,0 +1,50 @@ +package com.donaldy.basic.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 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/group24/448641125/src/com/donaldy/basic/expr/TokenParser.java b/group24/448641125/src/com/donaldy/basic/expr/TokenParser.java new file mode 100644 index 0000000000..38d5225c4f --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.donaldy.basic.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/group24/448641125/src/com/donaldy/basic/expr/TokenParserTest.java b/group24/448641125/src/com/donaldy/basic/expr/TokenParserTest.java new file mode 100644 index 0000000000..03d3146213 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.donaldy.basic.expr; + +import static org.junit.Assert.*; + +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()); + } + +} From 5066bfd6413c7be2f6fcc5f4e4d38d9e4a93775c Mon Sep 17 00:00:00 2001 From: "[Ren650119726]" <[102228177@qq.com]> Date: Tue, 18 Apr 2017 22:59:12 +0800 Subject: [PATCH 060/151] 4-16 --- .../275150374Learning/.idea/description.html | 16 ++++- group15/1512_656512403/.idea/description.html | 16 ++++- .../jvm/test/ClassFileloaderTest.java | 2 +- .../src/com/coding/basic/stack/InfixExpr.java | 66 +++++++++++++++++-- .../src/com/coding/basic/stack/Token.java | 49 ++++++++++++++ .../com/coding/basic/stack/TokenParser.java | 56 ++++++++++++++++ .../com/coderising/download/net_multisoc.htm | 15 +++++ 7 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/Token.java create mode 100644 group17/102228177/work4_16/src/com/coding/basic/stack/TokenParser.java diff --git a/group01/275150374/275150374Learning/.idea/description.html b/group01/275150374/275150374Learning/.idea/description.html index db5f129556..0f928c44a1 100644 --- a/group01/275150374/275150374Learning/.idea/description.html +++ b/group01/275150374/275150374Learning/.idea/description.html @@ -1 +1,15 @@ -Simple Java application that includes a class with main() method \ No newline at end of file +Simple Java application that includes a class with main() method \ No newline at end of file diff --git a/group15/1512_656512403/.idea/description.html b/group15/1512_656512403/.idea/description.html index db5f129556..0f928c44a1 100644 --- a/group15/1512_656512403/.idea/description.html +++ b/group15/1512_656512403/.idea/description.html @@ -1 +1,15 @@ -Simple Java application that includes a class with main() method \ No newline at end of file +Simple Java application that includes a class with main() method \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group17/102228177/work4_16/src/com/coderising/jvm/test/ClassFileloaderTest.java index 4e0b8e1001..3afc6ee711 100644 --- a/group17/102228177/work4_16/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group17/102228177/work4_16/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -24,7 +24,7 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; // static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; - static String path1 = "D:\\software\\taotao\\work4_09\\bin"; + static String path1 = "D:\\workspace\\work4_16\\bin"; static String path2 = "C:\temp"; static ClassFile clzFile = null; diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java index 5c04740bfb..a092602897 100644 --- a/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/InfixExpr.java @@ -1,5 +1,6 @@ package com.coding.basic.stack; - +import java.util.List; +import java.util.Stack; public class InfixExpr { String expr = null; @@ -7,12 +8,67 @@ public InfixExpr(String expr) { this.expr = expr; } - public float evaluate() { + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + if(opStack.isEmpty()){ + + opStack.push(token); + } else{ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } - return 0.0f; + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + 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"); } - - } \ No newline at end of file diff --git a/group17/102228177/work4_16/src/com/coding/basic/stack/Token.java b/group17/102228177/work4_16/src/com/coding/basic/stack/Token.java new file mode 100644 index 0000000000..364fe104f5 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/Token.java @@ -0,0 +1,49 @@ +package com.coding.basic.stack; +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 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/group17/102228177/work4_16/src/com/coding/basic/stack/TokenParser.java b/group17/102228177/work4_16/src/com/coding/basic/stack/TokenParser.java new file mode 100644 index 0000000000..c45a23aed1 --- /dev/null +++ b/group17/102228177/work4_16/src/com/coding/basic/stack/TokenParser.java @@ -0,0 +1,56 @@ +package com.coding.basic.stack; +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/group17/1282579502/src/com/coderising/download/net_multisoc.htm b/group17/1282579502/src/com/coderising/download/net_multisoc.htm index 5ddcba89af..852129b19a 100644 --- a/group17/1282579502/src/com/coderising/download/net_multisoc.htm +++ b/group17/1282579502/src/com/coderising/download/net_multisoc.htm @@ -488,3 +488,18 @@

Result

+ \ No newline at end of file From 1882b98dae1f477e7cc0ea88efc2b6b7d729b899 Mon Sep 17 00:00:00 2001 From: zj <2258659044@qq.com> Date: Tue, 18 Apr 2017 23:19:19 +0800 Subject: [PATCH 061/151] coding --- .../coding/basic/stack/expr/ExprIterator.java | 32 ++++++++ .../coding/basic/stack/expr/FixExprUtil.java | 81 +++++++++++++++++++ .../coding/basic/stack/expr/InfixExpr.java | 69 ++-------------- .../basic/stack/expr/InfixToPostfix.java | 56 +++++++++++++ .../com/coding/basic/stack/expr/Operator.java | 13 +++ .../coding/basic/stack/expr/PostfixExpr.java | 43 ++++++++++ .../coding/basic/stack/expr/PrefixExpr.java | 44 ++++++++++ .../basic/stack/expr/PostfixExprTest.java | 38 +++++++++ .../basic/stack/expr/PrefixExprTest.java | 46 +++++++++++ 9 files changed, 359 insertions(+), 63 deletions(-) create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java create mode 100644 group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PostfixExprTest.java create mode 100644 group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PrefixExprTest.java diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java new file mode 100644 index 0000000000..513cc901fb --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java @@ -0,0 +1,32 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.List; +import com.coding.basic.array.ArrayList; + + +/** + * 表达式迭代器 + * @author zj + * @since 2017-4-17 + */ +public class ExprIterator{ + + private List data = new ArrayList(); + private int cursor; + + public ExprIterator(String expr){ + this.data = FixExprUtil.FixExprToArray(expr); + } + + public boolean hasNext() { + return cursor != (data.size()); + } + + public String next() { + + int i = cursor; + cursor = (i+1); + return data.get(i); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java new file mode 100644 index 0000000000..0477bce3ec --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java @@ -0,0 +1,81 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.List; +import com.coding.basic.array.ArrayList; + +public class FixExprUtil { + + /** + * 运算 + * @param a 数字 + * @param oper 运算符 + * @param b 数字 + * @return + */ + public static float calculate(float a,Operator oper,float b) { + + String operFlag = oper.getFlag(); + + float res = 0f; + if (Operator.ADD.getFlag().equals(operFlag)) { + res = a + b; + } else if (Operator.SUB.getFlag().equals(operFlag)) { + res = a - b; + } else if (Operator.MULTY.getFlag().equals(operFlag)) { + res = a * b; + } else if (Operator.DIVIDE.getFlag().equals(operFlag)) { + res = a / b; + } + return res; + } + + /** + * 将字符串顺序逆置 + * @param str + * @return + */ + public static String reverse(String expr){ + + return new StringBuffer(expr).reverse().toString(); + } + + /** + * 将表达式字符串转换为List + * @param expr + * @return + */ + public static List FixExprToArray(String expr){ + + List ls = new ArrayList<>(); + + String[] strArr = expr.split(" "); + for (String str : strArr) { + parse(str,ls); + } + + return ls; + } + + public static void parse(String str,List ls){ + + char[] chr = str.toCharArray(); + StringBuilder token = new StringBuilder(); + + for (char c : chr) { + if(Operator.contains(c+"")){ + if(!"".equals(token.toString())){ + ls.add(token.toString()); + token = new StringBuilder(); + } + ls.add(c+""); + }else{ + token.append(c); + } + } + if(!"".equals(token.toString())){ + ls.add(token.toString()); + } + + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java index 9d34a17fb5..0ee14605fc 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java @@ -1,19 +1,14 @@ package com.coding.basic.stack.expr; -import com.coding.basic.Iterator; import com.coding.basic.stack.Stack; import com.coding.basic.stack.StackUtil; public class InfixExpr { String expr = null; - char[] data = null; - private static final String operatorsStr = "+-*/"; - public InfixExpr(String expr) { this.expr = expr; - this.data = expr.toCharArray(); } public float evaluate() { @@ -23,7 +18,7 @@ public float evaluate() { //操作栈 Stack operStack = new Stack<>(); - splitInfixExpr(dataStack,operStack); + parseExpr(dataStack,operStack); return summary(dataStack,operStack); } @@ -34,12 +29,12 @@ public float evaluate() { * * @return */ - private void splitInfixExpr(Stack dataStack,Stack operStack) { + private void parseExpr(Stack dataStack,Stack operStack) { - Itr it = new Itr(); + ExprIterator it = new ExprIterator(expr); while(it.hasNext()){ String element = it.next(); - if (operatorsStr.contains(element)) { + if (Operator.contains(element)) { putOpersToStack(dataStack,operStack, element); } else { dataStack.push(Float.parseFloat(element)); @@ -79,30 +74,6 @@ private void putOpersToStack(Stack dataStack,Stack operStack, S } operStack.push(thisOper); } - - /** - * 运算 - * @param a 数字 - * @param oper 运算符 - * @param b 数字 - * @return - */ - private float calculate(float a,Operator oper,float b) { - - String operFlag = oper.getFlag(); - - float res = 0f; - if (Operator.ADD.getFlag().equals(operFlag)) { - res = a + b; - } else if (Operator.SUB.getFlag().equals(operFlag)) { - res = a - b; - } else if (Operator.MULTY.getFlag().equals(operFlag)) { - res = a * b; - } else if (Operator.DIVIDE.getFlag().equals(operFlag)) { - res = a / b; - } - return res; - } /** * 运算距栈顶最近两个元素的值并压回原栈 @@ -123,7 +94,7 @@ private void calculateToStack(Stack dataStack,Stack operStack,b } Operator oper = operStack.pop(); - float res = calculate(a,oper,b); + float res = FixExprUtil.calculate(a,oper,b); dataStack.push(res); } @@ -142,33 +113,5 @@ private float summary(Stack dataStack,Stack operStack) { } return dataStack.pop(); } - - private class Itr implements Iterator { - - int cursor; - - @Override - public boolean hasNext() { - return cursor != (expr.length()); - } - - @Override - public String next() { - - StringBuilder val = new StringBuilder(); - for (int i = cursor; i < data.length; i++) { - if (operatorsStr.contains(data[i] + "")) { - if ("".equals(val.toString())) { - val.append(data[i]); - this.cursor = (i + 1); - } - break; - } else { - val.append(data[i]); - this.cursor = (i + 1); - } - } - return val.toString(); - } - } + } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..02aa5b5bff --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,56 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; +import com.coding.basic.stack.StackUtil; + +public class InfixToPostfix { + + public static String convert(String expr) { + + ExprIterator it = new ExprIterator(expr); + + Stack s1 = new Stack<>(); + + Stack s2 = new Stack<>(); + + int preLevel,thisLevel; + + while(it.hasNext()){ + + String element = it.next(); + if(Operator.contains(element)){//运算符 + while(true){ + if(s1.isEmpty()){ + s1.push(element); + break; + }else{ + preLevel = Operator.getLevelByFlag(s1.peek()); + thisLevel = Operator.getLevelByFlag(element); + if(thisLevel>preLevel){ + s1.push(element); + break; + }else{ + s2.push(s1.pop()); + } + } + } + }else{ + s2.push(element); + } + } + + while(!s1.isEmpty()){ + s2.push(s1.pop()); + } + StackUtil.reverse(s2); + return s2.toString(); + } + + public static void main(String[] args) { + + String a = "9+(3-1)*3+10/2"; + String post = InfixToPostfix.convert(a); + System.out.println(post); + + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java index 3629e99482..f6de250fc4 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java @@ -37,6 +37,19 @@ public static Operator getOperator(String flag){ return null; } + public static boolean contains(String flag){ + + if(ADD.flag.equals(flag)){ + return true; + }else if(SUB.flag.equals(flag)){ + return true; + }else if(MULTY.flag.equals(flag)){ + return true; + }else if(DIVIDE.flag.equals(flag)){ + return true; + } + return false; + } public String getFlag() { return flag; } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..b406bc3ead --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,43 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +public class PostfixExpr { + + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + //数据栈 + Stack dataStack = new Stack<>(); + + parseExpr(dataStack,null); + + return dataStack.peek(); + } + + /** + * 解析表达式 + * @return + */ + private void parseExpr(Stack dataStack,Stack operStack) { + + ExprIterator it = new ExprIterator(expr); + float a,b,res; + while(it.hasNext()){ + String element = it.next(); + if (Operator.contains(element)) { + b = dataStack.pop(); + a = dataStack.pop(); + res = FixExprUtil.calculate(a, Operator.getOperator(element), b); + dataStack.push(res); + } else { + dataStack.push(Float.parseFloat(element)); + } + } + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..a11e9a13ba --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,44 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +public class PrefixExpr { + + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + //数据栈 + Stack dataStack = new Stack<>(); + + parseExpr(dataStack,null); + + return dataStack.peek(); + } + + /** + * 解析表达式 + * @return + */ + private void parseExpr(Stack dataStack,Stack operStack) { + + ExprIterator it = new ExprIterator(FixExprUtil.reverse(expr)); + float a,b,res; + while(it.hasNext()){ + String element = it.next(); + if (Operator.contains(element)) { + a = dataStack.pop(); + b = dataStack.pop(); + res = FixExprUtil.calculate(a, Operator.getOperator(element), b); + dataStack.push(res); + } else { + dataStack.push(Float.parseFloat(element)); + } + } + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PostfixExprTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..97ec425a7b --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,38 @@ +package test.com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.expr.PostfixExpr; + +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/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PrefixExprTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..e866223a4e --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,46 @@ +package test.com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.expr.PrefixExpr; + +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); + } + + + } + +} From 83fb8ce3c2b51f61d549e67cac3ef1b814315f9e Mon Sep 17 00:00:00 2001 From: zj <2258659044@qq.com> Date: Wed, 19 Apr 2017 09:40:17 +0800 Subject: [PATCH 062/151] coding --- .../src/com/coderising/jvm/attr/CodeAttr.java | 17 +- .../src/com/coderising/jvm/clz/ClassFile.java | 32 +++- .../src/com/coderising/jvm/cmd/BiPushCmd.java | 21 +++ .../coderising/jvm/cmd/ByteCodeCommand.java | 125 ++++++++++++++ .../com/coderising/jvm/cmd/CommandParser.java | 155 ++++++++++++++++++ .../com/coderising/jvm/cmd/GetFieldCmd.java | 21 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 19 +++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 21 +++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 21 +++ .../src/com/coderising/jvm/cmd/LdcCmd.java | 29 ++++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 23 +++ .../com/coderising/jvm/cmd/OneOperandCmd.java | 27 +++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 19 +++ .../com/coderising/jvm/cmd/TwoOperandCmd.java | 67 ++++++++ .../coderising/jvm/constant/ClassInfo.java | 5 + .../coderising/jvm/constant/ConstantInfo.java | 12 ++ .../coderising/jvm/constant/ConstantPool.java | 23 ++- .../coderising/jvm/constant/FieldRefInfo.java | 5 + .../jvm/constant/MethodRefInfo.java | 6 + .../jvm/constant/NameAndTypeInfo.java | 5 + .../jvm/constant/NullConstantInfo.java | 4 + .../coderising/jvm/constant/StringInfo.java | 6 + .../com/coderising/jvm/constant/UTF8Info.java | 4 + .../jvm/loader/ClassFileParser.java | 9 +- .../src/com/coderising/jvm/method/Method.java | 11 ++ .../jvm/print/ClassFilePrinter.java | 52 ++++++ .../jvm/print/ConstantPoolPrinter.java | 91 ++++++++++ .../coderising/jvm/ClassFileloaderTest.java | 82 ++++++++- 29 files changed, 916 insertions(+), 15 deletions(-) create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java index 3a2f0e6988..64e6226561 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/attr/CodeAttr.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; @@ -12,17 +14,19 @@ public class CodeAttr extends AttributeInfo { private int maxLocals ; private int codeLen ; private String code; + private ByteCodeCommand[] cmds ; private List attributeInfos = new ArrayList<>(); - public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code ) { + 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 static CodeAttr parse(ConstantPool pool,ByteCodeIterator iter){ int attrNameIndex = iter.nextU2ToInt(); @@ -31,11 +35,13 @@ public static CodeAttr parse(ConstantPool pool,ByteCodeIterator iter){ int maxLocals = iter.nextU2ToInt(); int codeLen = iter.nextU4ToInt(); String code = iter.nextUxToHexString(codeLen); - CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code); + ByteCodeCommand[] cmds = CommandParser.parse(pool.getClzFile(),code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code,cmds); //解析exception_table start TODO + @SuppressWarnings("unused") int exceptionTabLen = iter.nextU2ToInt(); - System.out.println("exception_table 的个数为"+exceptionTabLen); + //System.out.println("exception_table 的个数为"+exceptionTabLen); //解析exception_table end TODO codeAttr.setAttributeInfos(AttributeInfo.parseAttributes(pool, iter)); @@ -43,6 +49,9 @@ public static CodeAttr parse(ConstantPool pool,ByteCodeIterator iter){ return codeAttr; } + public ByteCodeCommand[] getCmds() { + return cmds; + } public int getMaxStack() { return maxStack; diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java index c21a0988e5..534bc36cba 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/clz/ClassFile.java @@ -67,6 +67,34 @@ public List getMethods() { return methods; } + 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(){ + 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; + } public void print(){ @@ -80,12 +108,12 @@ public void print(){ } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.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(); } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..03db32ccc9 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.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(); + } + + + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..4c8b21ab09 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,125 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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; + } +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..0dd0573ae5 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,155 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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) { + + 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"); + } + + } + + calcuateOffset(cmds); + + 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; + } + + 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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..92fe286363 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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); + } + + + + +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..52a7550d12 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..c6efbae530 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..a17c51a81d --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..00f9a5a699 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..a43c8bd964 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..461bb4e2a5 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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; + } + +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..6b1b8c284c --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..00b29e1fbc --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..334eec9f98 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java index e12b3e164e..c837b9d838 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ClassInfo.java @@ -21,4 +21,9 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java index c8035ae876..35a3d873a9 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantInfo.java @@ -26,4 +26,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); + + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java index 0e940b78d0..d641ea15c0 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/ConstantPool.java @@ -3,14 +3,18 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.clz.ClassFile; + public class ConstantPool { private List constantInfos = new ArrayList(); + private ClassFile clzFile; - public ConstantPool(){ - + public ConstantPool(ClassFile clzFile){ + this.clzFile = clzFile; } + public void addConstantInfo(ConstantInfo info){ this.constantInfos.add(info); @@ -23,7 +27,20 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } + + public List getConstantInfos() { + return constantInfos; + } + + public void setConstantInfos(List constantInfos) { + this.constantInfos = constantInfos; + } + + public ClassFile getClzFile() { + return clzFile; + } + } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java index 7ff9d5fb77..804e41a393 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -51,4 +51,9 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + + visitor.visitFieldRef(this); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java index 0feffa65b5..68d84ad685 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -49,6 +49,12 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + + visitor.visitMethodRef(this); + } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java index dcac7f97c4..c22a7bfbca 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -42,4 +42,9 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java index fa90d110fe..80cc827f18 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -9,5 +9,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java index d01065fd53..56f5daa724 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/StringInfo.java @@ -22,5 +22,11 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + + visitor.visitString(this); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java index 0aa9ee045b..858f1b212d 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/constant/UTF8Info.java @@ -26,5 +26,9 @@ public String getValue() { public void setValue(String value) { this.value = value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java index bd1fa61d5b..0d49151217 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/loader/ClassFileParser.java @@ -32,7 +32,7 @@ public ClassFile parse(byte[] codes) throws NotAClassFileException { clazzFile.setMajorVersion(iterator.nextU2ToInt()); - clazzFile.setConstPool(parseConstantPool(iterator)); + clazzFile.setConstPool(parseConstantPool(iterator,clazzFile)); clazzFile.setAccessFlag(parseAccessFlag(iterator)); @@ -67,9 +67,9 @@ private ClassIndex parseClassInfex(ByteCodeIterator iter){ return classIndex; } - private ConstantPool parseConstantPool(ByteCodeIterator iter){ + private ConstantPool parseConstantPool(ByteCodeIterator iter,ClassFile clazzFile){ - ConstantPool pool = new ConstantPool(); + ConstantPool pool = new ConstantPool(clazzFile); pool.addConstantInfo(new NullConstantInfo()); try { @@ -129,8 +129,9 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter){ private void parseInterfaces(ByteCodeIterator iter){ + @SuppressWarnings("unused") int interfaceCount = iter.nextU2ToInt(); - System.out.println("接口数量为:"+interfaceCount); + //System.out.println("接口数量为:"+interfaceCount); // TODO } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java index c8d8065df8..245ccdc558 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java @@ -4,6 +4,8 @@ import java.util.List; import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.cmd.ByteCodeCommand; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; @@ -35,7 +37,16 @@ public static Method parse(ConstantPool pool, ByteCodeIterator iter){ return method; } + public ByteCodeCommand[] getCmds() { + for (AttributeInfo attributeInfo : attributeInfos) { + if(attributeInfo instanceof CodeAttr){ + return ((CodeAttr) attributeInfo).getCmds(); + } + } + return null; + } + public int getAccessFlag() { return accessFlag; } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..ee99162a4d --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.exception.NotAClassFileException; +import com.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()+"\n"); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "test.com.coderising.jvm.EmployeeV1"; + + ClassFile clzFile = null; + try { + clzFile = loader.loadClass(className); + } catch (NotAClassFileException e) { + e.printStackTrace(); + } + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..9abd6ca1ed --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,91 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } + + private void printSpaceAfterConsName(String consBeforStr){ + + String bashStr = (pool.getSize()+1)+"="+"NameAndType "; + int bashLen = bashStr.length(); + int offset = bashLen-consBeforStr.length(); + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java index 3f763912fc..2a18bee6d7 100644 --- a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java @@ -10,6 +10,10 @@ import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; @@ -24,8 +28,8 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "test/com/coderising/jvm/EmployeeV1"; - //static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; - static String path1 = "E:\\githubRepository\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + //static String path1 = "E:\\githubRepository\\coding2017\\group12\\2258659044\\zj-2017\\bin"; static String path2 = "C:\temp"; @@ -268,4 +272,78 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } + + @Test + public void testByteCodeCommand(){ + { + Method initMethod = 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 = 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 = 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 = 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); + } } \ 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 063/151] 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 04167660c88cbf42f2dfb1beb8faa4775d627776 Mon Sep 17 00:00:00 2001 From: gongxun Date: Wed, 19 Apr 2017 14:26:30 +0800 Subject: [PATCH 064/151] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AD=97=E8=8A=82?= =?UTF-8?q?=E7=A0=81=E5=91=BD=E4=BB=A4=E7=9A=84=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.16/cmd/CommandParser.java | 193 +++++++++++------- group17/785396327/4.5/clz/ClassFile.java | 21 +- .../4.5/test/ClassFileloaderTest.java | 82 ++++---- 3 files changed, 177 insertions(+), 119 deletions(-) diff --git a/group17/785396327/4.16/cmd/CommandParser.java b/group17/785396327/4.16/cmd/CommandParser.java index 5f5956350d..c76ca4af52 100644 --- a/group17/785396327/4.16/cmd/CommandParser.java +++ b/group17/785396327/4.16/cmd/CommandParser.java @@ -3,6 +3,7 @@ import clz.ClassFile; import constant.ClassInfo; +import java.util.ArrayList; import java.util.List; /** @@ -46,81 +47,125 @@ public class CommandParser { public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { CommandIterator commandIterator = new CommandIterator(codes); - String command = commandIterator.next2CharAsString().toUpperCase(); - if (command.equals(aconst_null)) { - NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); - noOperandCmd.setOffset(1); - } else if (command.equals(new_object)) { - NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, command); - int oprand1 = commandIterator.next2CharAsInt(); - int oprand2 = commandIterator.next2CharAsInt(); - newObjectCmd.setOprand1(oprand1); - newObjectCmd.setOprand2(oprand2); - - } else if (command.equals(lstore)) { - - } else if (command.equals(invokespecial)) { - - } else if (command.equals(invokevirtual)) { - - } else if (command.equals(getfield)) { - GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, command); - } else if (command.equals(putfield)) { - PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, command); - } else if (command.equals(getstatic)) { - GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, command); - } else if (command.equals(ldc)) { - LdcCmd ldcCmd = new LdcCmd(clzFile, command); - } else if (command.equals(dup)) { - - } else if (command.equals(bipush)) { - BiPushCmd biPushCmd = new BiPushCmd(clzFile, command); - } else if (command.equals(aload_0)) { - NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); - } else if (command.equals(aload_1)) { - NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); - } else if (command.equals(aload_2)) { - NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); - } else if (command.equals(iload)) { - - } else if (command.equals(iload_2)) { - - } else if (command.equals(iload_1)) { - - } else if (command.equals(iload_3)) { - - } else if (command.equals(fload_3)) { - - } else if (command.equals(voidreturn)) { - - } else if (command.equals(ireturn)) { - - } else if (command.equals(freturn)) { - - } else if (command.equals(astore_1)) { - - } else if (command.equals(if_icmp_ge)) { - - } else if (command.equals(if_icmple)) { - - } else if (command.equals(goto_no_condition)) { - - } else if (command.equals(iconst_0)) { - - } else if (command.equals(iconst_1)) { - - } else if (command.equals(istore_1)) { - - } else if (command.equals(istore_2)) { - - } else if (command.equals(iadd)) { - - } else if (command.equals(iinc)) { - - } else { - throw new RuntimeException("wrong command : " + command); + List commandList = new ArrayList(); + while (commandIterator.hasNext()) { + String command = commandIterator.next2CharAsString().toUpperCase(); + if (command.equals(aconst_null)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(new_object)) { + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, command); + newObjectCmd.setOprand1(commandIterator.next2CharAsInt()); + newObjectCmd.setOprand2(commandIterator.next2CharAsInt()); + newObjectCmd.setOffset(newObjectCmd.getLength()); + commandList.add(newObjectCmd); + } else if (command.equals(lstore)) { + + } else if (command.equals(invokespecial)) { + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, command); + invokeSpecialCmd.setOprand1(commandIterator.next2CharAsInt()); + invokeSpecialCmd.setOprand2(commandIterator.next2CharAsInt()); + invokeSpecialCmd.setOffset(invokeSpecialCmd.getLength()); + commandList.add(invokeSpecialCmd); + } else if (command.equals(invokevirtual)) { + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, command); + invokeVirtualCmd.setOprand1(commandIterator.next2CharAsInt()); + invokeVirtualCmd.setOprand2(commandIterator.next2CharAsInt()); + invokeVirtualCmd.setOffset(invokeVirtualCmd.getLength()); + commandList.add(invokeVirtualCmd); + } else if (command.equals(getfield)) { + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, command); + } else if (command.equals(putfield)) { + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, command); + putFieldCmd.setOprand1(commandIterator.next2CharAsInt()); + putFieldCmd.setOprand2(commandIterator.next2CharAsInt()); + putFieldCmd.setOffset(putFieldCmd.getLength()); + commandList.add(putFieldCmd); + } else if (command.equals(getstatic)) { + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, command); + getStaticFieldCmd.setOprand1(commandIterator.next2CharAsInt()); + getStaticFieldCmd.setOprand2(commandIterator.next2CharAsInt()); + getStaticFieldCmd.setOffset(getStaticFieldCmd.getLength()); + commandList.add(getStaticFieldCmd); + } else if (command.equals(ldc)) { + LdcCmd ldcCmd = new LdcCmd(clzFile, command); + ldcCmd.setOperand(commandIterator.next2CharAsInt()); + ldcCmd.setOffset(ldcCmd.getLength()); + commandList.add(ldcCmd); + } else if (command.equals(dup)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(bipush)) { + BiPushCmd biPushCmd = new BiPushCmd(clzFile, command); + biPushCmd.setOperand(commandIterator.next2CharAsInt()); + biPushCmd.setOffset(biPushCmd.getLength()); + commandList.add(biPushCmd); + } else if (command.equals(aload_0)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(aload_1)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(aload_2)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(iload)) { + + } else if (command.equals(iload_2)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(iload_1)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(iload_3)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(fload_3)) { + + } else if (command.equals(voidreturn)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(ireturn)) { + + } else if (command.equals(freturn)) { + + } else if (command.equals(astore_1)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command); + noOperandCmd.setOffset(noOperandCmd.getLength()); + commandList.add(noOperandCmd); + } else if (command.equals(if_icmp_ge)) { + + } else if (command.equals(if_icmple)) { + + } else if (command.equals(goto_no_condition)) { + + } else if (command.equals(iconst_0)) { + + } else if (command.equals(iconst_1)) { + + } else if (command.equals(istore_1)) { + + } else if (command.equals(istore_2)) { + + } else if (command.equals(iadd)) { + + } else if (command.equals(iinc)) { + + } else { + throw new RuntimeException("wrong command : " + command); + } } - return null; + calcuateOffset(commandList); + return commandList.toArray(new ByteCodeCommand[commandList.size()]); } private static void calcuateOffset(List cmds) { diff --git a/group17/785396327/4.5/clz/ClassFile.java b/group17/785396327/4.5/clz/ClassFile.java index 27e78451c5..fe3f0f500e 100644 --- a/group17/785396327/4.5/clz/ClassFile.java +++ b/group17/785396327/4.5/clz/ClassFile.java @@ -92,13 +92,26 @@ private String getSuperClassName(){ return superClass.getClassName(); } - public Method getMethod(String methodName, String paramAndReturnType){ - - + public Method getMethod(String methodName, String paramAndReturnType) { + if (methods != null) { + for (Method method : methods) { + String name = getConstantPool().getUTF8String(method.getNameIndex()); + String desc = getConstantPool().getUTF8String(method.getDescriptorIndex()); + if(name.equals(methodName)&&desc.equals(paramAndReturnType)) + return method; + } + } return null; } public Method getMainMethod(){ - + if (methods != null) { + for (Method method : methods) { + String name = getConstantPool().getUTF8String(method.getNameIndex()); + String desc = getConstantPool().getUTF8String(method.getDescriptorIndex()); + if(name.equals("main")&&desc.equals("([Ljava/lang/String;)V")) + return method; + } + } return null; } } diff --git a/group17/785396327/4.5/test/ClassFileloaderTest.java b/group17/785396327/4.5/test/ClassFileloaderTest.java index 2a8badce36..2276ee4eaf 100644 --- a/group17/785396327/4.5/test/ClassFileloaderTest.java +++ b/group17/785396327/4.5/test/ClassFileloaderTest.java @@ -228,36 +228,36 @@ public void testMethods(){ "2ab700012a2bb500022a1cb50003b1"); } -// { -// Method m = methods.get(1); -// assertMethodEquals(pool,m, -// "setName", -// "(Ljava/lang/String;)V", -// "2a2bb50002b1"); -// -// } -// { -// Method m = methods.get(2); -// assertMethodEquals(pool,m, -// "setAge", -// "(I)V", -// "2a1bb50003b1"); -// } -// { -// Method m = methods.get(3); -// assertMethodEquals(pool,m, -// "sayHello", -// "()V", -// "b200041205b60006b1"); -// -// } -// { -// Method m = methods.get(4); -// assertMethodEquals(pool,m, -// "main", -// "([Ljava/lang/String;)V", -// "bb0007591208101db700094c2bb6000ab1"); -// } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb50002b1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50003b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b200041205b60006b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb0007591208101db700094c2bb6000ab1"); + } } private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ @@ -277,13 +277,13 @@ public void testByteCodeCommand(){ ByteCodeCommand [] cmds = initMethod.getCmds(); assertOpCodeEquals("0: aload_0", cmds[0]); - assertOpCodeEquals("1: invokespecial #12", cmds[1]); + assertOpCodeEquals("1: invokespecial #1", cmds[1]); assertOpCodeEquals("4: aload_0", cmds[2]); assertOpCodeEquals("5: aload_1", cmds[3]); - assertOpCodeEquals("6: putfield #15", cmds[4]); + assertOpCodeEquals("6: putfield #2", cmds[4]); assertOpCodeEquals("9: aload_0", cmds[5]); assertOpCodeEquals("10: iload_2", cmds[6]); - assertOpCodeEquals("11: putfield #17", cmds[7]); + assertOpCodeEquals("11: putfield #3", cmds[7]); assertOpCodeEquals("14: return", cmds[8]); } @@ -293,7 +293,7 @@ public void testByteCodeCommand(){ assertOpCodeEquals("0: aload_0", cmds[0]); assertOpCodeEquals("1: aload_1", cmds[1]); - assertOpCodeEquals("2: putfield #15", cmds[2]); + assertOpCodeEquals("2: putfield #2", cmds[2]); assertOpCodeEquals("5: return", cmds[3]); } @@ -302,9 +302,9 @@ public void testByteCodeCommand(){ 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("0: getstatic #4", cmds[0]); + assertOpCodeEquals("3: ldc #5", cmds[1]); + assertOpCodeEquals("5: invokevirtual #6", cmds[2]); assertOpCodeEquals("8: return", cmds[3]); } @@ -314,14 +314,14 @@ public void testByteCodeCommand(){ ByteCodeCommand [] cmds = mainMethod.getCmds(); - assertOpCodeEquals("0: new #1", cmds[0]); + assertOpCodeEquals("0: new #7", cmds[0]); assertOpCodeEquals("3: dup", cmds[1]); - assertOpCodeEquals("4: ldc #43", cmds[2]); + assertOpCodeEquals("4: ldc #8", cmds[2]); assertOpCodeEquals("6: bipush 29", cmds[3]); - assertOpCodeEquals("8: invokespecial #45", cmds[4]); + assertOpCodeEquals("8: invokespecial #9", cmds[4]); assertOpCodeEquals("11: astore_1", cmds[5]); assertOpCodeEquals("12: aload_1", cmds[6]); - assertOpCodeEquals("13: invokevirtual #47", cmds[7]); + assertOpCodeEquals("13: invokevirtual #10", cmds[7]); assertOpCodeEquals("16: return", cmds[8]); } From 67a8b47adb6ff31b61f12d6975431310def4623c Mon Sep 17 00:00:00 2001 From: gongxun Date: Wed, 19 Apr 2017 14:27:46 +0800 Subject: [PATCH 065/151] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.16/cmd/CommandParser.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/group17/785396327/4.16/cmd/CommandParser.java b/group17/785396327/4.16/cmd/CommandParser.java index c76ca4af52..02d06cd275 100644 --- a/group17/785396327/4.16/cmd/CommandParser.java +++ b/group17/785396327/4.16/cmd/CommandParser.java @@ -76,6 +76,10 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { commandList.add(invokeVirtualCmd); } else if (command.equals(getfield)) { GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, command); + getFieldCmd.setOprand1(commandIterator.next2CharAsInt()); + getFieldCmd.setOprand2(commandIterator.next2CharAsInt()); + getFieldCmd.setOffset(getFieldCmd.getLength()); + commandList.add(getFieldCmd); } else if (command.equals(putfield)) { PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, command); putFieldCmd.setOprand1(commandIterator.next2CharAsInt()); From ed72c106f23a0fbae787fd93539947bb2a2c29fd Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Wed, 19 Apr 2017 17:15:47 +0800 Subject: [PATCH 066/151] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/basic/queue/CircleQueue.java | 5 + .../com/coding/basic/queue/Josephus.java | 42 +++++ .../com/coding/basic/queue/JosephusTest.java | 26 ++++ .../com/coding/basic/{ => queue}/Queue.java | 2 +- .../basic/queue/QueueWithTwoStacks.java | 38 +++++ .../basic/stack/expr/InfixToPostfix.java | 14 ++ .../coding/basic/stack/expr/PostfixExpr.java | 18 +++ .../basic/stack/expr/PostfixExprTest.java | 36 +++++ .../coding/basic/stack/expr/PrefixExpr.java | 17 +++ .../basic/stack/expr/PrefixExprTest.java | 44 ++++++ .../com/coding/basic/stack/expr/Token.java | 49 ++++++ .../coding/basic/stack/expr/TokenParser.java | 56 +++++++ .../basic/stack/expr/TokenParserTest.java | 40 +++++ .../com/coderising/jvm/attr/CodeAttr.java | 111 ++++++++------ .../coderising/jvm/attr/LineNumberTable.java | 13 ++ .../jvm/attr/LocalVariableTable.java | 14 ++ .../com/coderising/jvm/clz/ClassFile.java | 87 +++++++---- .../com/coderising/jvm/cmd/BiPushCmd.java | 23 +++ .../coderising/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++ .../com/coderising/jvm/cmd/CommandParser.java | 144 ++++++++++++++++++ .../com/coderising/jvm/cmd/GetFieldCmd.java | 22 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 23 +++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 23 +++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../com/coderising/jvm/cmd/LdcCmd.java | 29 ++++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 23 +++ .../com/coderising/jvm/cmd/OneOperandCmd.java | 27 ++++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 19 +++ .../com/coderising/jvm/cmd/TwoOperandCmd.java | 67 ++++++++ .../com/coderising/jvm/method/Method.java | 4 + .../jvm/print/ClassFilePrinter.java | 54 +++++++ .../jvm/print/ConstantPoolPrinter.java | 25 +++ .../jvm/test/ClassFileloaderTest.java | 83 +++++++++- 34 files changed, 1272 insertions(+), 75 deletions(-) create mode 100644 group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java create mode 100644 group27/383117348/data-structure/com/coding/basic/queue/Josephus.java create mode 100644 group27/383117348/data-structure/com/coding/basic/queue/JosephusTest.java rename group27/383117348/data-structure/com/coding/basic/{ => queue}/Queue.java (91%) create mode 100644 group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacks.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExprTest.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExprTest.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/Token.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParser.java create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParserTest.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/CommandParser.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java diff --git a/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..ff94d5e21a --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,5 @@ +package com.coding.basic.queue; + +public class CircleQueue { + +} diff --git a/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java b/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..9ff4187a53 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java @@ -0,0 +1,42 @@ +package com.coding.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) { + if (n < m || n <= 0 || m <= 0) { + throw new RuntimeException("传入参数有误,执行失败!"); + } + //保存被杀掉的数 + List ints = new ArrayList(); + //报数 + int count = 0; + while(ints.size()!=n){ + + for(int i=0;i list = execute(7, 2); + System.out.println(list); + } + +} diff --git a/group27/383117348/data-structure/com/coding/basic/queue/JosephusTest.java b/group27/383117348/data-structure/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..12a3ec45be --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,26 @@ +package com.coding.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/group27/383117348/data-structure/com/coding/basic/Queue.java b/group27/383117348/data-structure/com/coding/basic/queue/Queue.java similarity index 91% rename from group27/383117348/data-structure/com/coding/basic/Queue.java rename to group27/383117348/data-structure/com/coding/basic/queue/Queue.java index 4bd32c067b..11b191bf89 100644 --- a/group27/383117348/data-structure/com/coding/basic/Queue.java +++ b/group27/383117348/data-structure/com/coding/basic/queue/Queue.java @@ -1,4 +1,4 @@ -package com.coding.basic; +package com.coding.basic.queue; import org.junit.Test; diff --git a/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacks.java b/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..7a6a11a3e4 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,38 @@ +package com.coding.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/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..dcee6ecadf --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,14 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} \ No newline at end of file diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..db7e5a4c6a --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,18 @@ +package com.coding.basic.stack.expr; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + + return 0.0f; + } + + +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExprTest.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..cc7efb5d40 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,36 @@ +package com.coding.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/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..f3b4953b51 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,17 @@ +package com.coding.basic.stack.expr; +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} \ No newline at end of file diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExprTest.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..9cfaa64570 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,44 @@ +package com.coding.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/group27/383117348/data-structure/com/coding/basic/stack/expr/Token.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..2d78610e7a --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,49 @@ +package com.coding.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 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; + } + + + +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParser.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..58ee229f9a --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,56 @@ +package com.coding.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/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParserTest.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..3562e42508 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack.expr; +import static org.junit.Assert.*; + +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()); + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java index b2779f1b70..a47357ec09 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/CodeAttr.java @@ -1,6 +1,9 @@ package com.coderising.jvm.attr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo { @@ -13,22 +16,24 @@ 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 */) { + 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) { @@ -39,47 +44,61 @@ public void setLocalVariableTable(LocalVariableTable t) { this.localVarTable = t; } - public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { int attributeNameIndex = iter.nextU2Int(); - int attributeLength = iter.nextU4Integer(); - int maxStack = iter.nextU2Int(); - int maxLocals = iter.nextU2Int(); - - int length = iter.nextU4Integer(); - String code = iter.nextUxToHexString(length); - - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, length, code); - - int exceptionTableLength = iter.nextU2Int(); - if (exceptionTableLength > 0) { - String exceptionTable = iter.nextUxToHexString(exceptionTableLength); - throw new RuntimeException("解析异常表异常:"+exceptionTable); - } - - int attributesCount = iter.nextU2Int(); - for (int i = 0; i < attributesCount; i++) { - int subAttributeNameIndex = iter.nextU2Int(); - iter.back(2); - - String subAttributeName = clzFile.getConstantPool().getUTF8String(subAttributeNameIndex); - - if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { - - LineNumberTable lineNumberTable = LineNumberTable.parse(iter); - codeAttr.setLineNumberTable(lineNumberTable); - - } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LOCAL_VAR_TABLE)) { - - LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); - codeAttr.setLocalVariableTable(localVariableTable); - - } else { - throw new RuntimeException("解析subAttribute异常-subAttributeName:"+subAttributeName); - } - - } - - return codeAttr; + int attributeLength = iter.nextU4Integer(); + int maxStack = iter.nextU2Int(); + int maxLocals = iter.nextU2Int(); + int length = iter.nextU4Integer(); + String code = iter.nextUxToHexString(length); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, length, code,cmds); + + int exceptionTableLength = iter.nextU2Int(); + if (exceptionTableLength > 0) { + String exceptionTable = iter.nextUxToHexString(exceptionTableLength); + throw new RuntimeException("解析异常表异常:" + exceptionTable); + } + + int attributesCount = iter.nextU2Int(); + for (int i = 0; i < attributesCount; i++) { + int subAttributeNameIndex = iter.nextU2Int(); + iter.back(2); + + String subAttributeName = clzFile.getConstantPool().getUTF8String(subAttributeNameIndex); + + if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LINE_NUM_TABLE)) { + + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + + } else if (null != subAttributeName && subAttributeName.equalsIgnoreCase(AttributeInfo.LOCAL_VAR_TABLE)) { + + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + + } else { + throw new RuntimeException("解析subAttribute异常-subAttributeName:" + subAttributeName); + } + + } + + return codeAttr; + } + + public String toString(ConstantPool pool) { + StringBuilder buffer = new StringBuilder(); + // buffer.append("Code:").append(code).append("\n"); + for (int i = 0; i < cmds.length; i++) { + buffer.append(cmds[i].toString(pool)).append("\n"); + } + buffer.append("\n"); + buffer.append(this.lineNumTable.toString()); + buffer.append(this.localVarTable.toString(pool)); + return buffer.toString(); } private void setStackMapTable(StackMapTable t) { diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java index 9c87155ca3..8a5b17f7e2 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LineNumberTable.java @@ -53,5 +53,18 @@ public static LineNumberTable parse(ByteCodeIterator iter) { return lineNumberTable; } + + + 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/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java index abbdae87d5..40495c9756 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; public class LocalVariableTable extends AttributeInfo { @@ -36,5 +37,18 @@ 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(); + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java b/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java index 9827aa2937..48c856053a 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/clz/ClassFile.java @@ -9,81 +9,116 @@ import com.coderising.jvm.method.Method; public class ClassFile { - + private int minorVersion; private int majorVersion; - + private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; private List fields = new ArrayList(); private List methods = new ArrayList(); - + public ClassIndex getClzIndex() { return clzIndex; } + public AccessFlag getAccessFlag() { return accessFlag; } + public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - public ConstantPool getConstantPool() { + + public ConstantPool getConstantPool() { return pool; } + public int getMinorVersion() { return minorVersion; } + public void setMinorVersion(int minorVersion) { this.minorVersion = minorVersion; } + public int getMajorVersion() { return majorVersion; } + public void setMajorVersion(int majorVersion) { this.majorVersion = majorVersion; } + public void setConstPool(ConstantPool pool) { this.pool = pool; - + } + public void setClassIndex(ClassIndex clzIndex) { - this.clzIndex = clzIndex; + this.clzIndex = clzIndex; } - - public void addField(Field f){ + + public void addField(Field f) { this.fields.add(f); } - public List getFields(){ + + public List getFields() { return this.fields; } - public void addMethod(Method m){ + + public void addMethod(Method m) { this.methods.add(m); } + public List getMethods() { return methods; } - - - public void print(){ - - if(this.accessFlag.isPublicClass()){ + + 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()); - - - } - - private String getClassName(){ + System.out.println("Class Name:" + getClassName()); + + System.out.println("Super Class Name:" + getSuperClassName()); + + } + + public String getClassName() { int thisClassIndex = this.clzIndex.getThisClassIndex(); - ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } - private String getSuperClassName(){ - ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + + public String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } + + public Method getMethod(String methodName, String paramAndReturnType) { + Method method = null; + for(Method m : methods){ + String name = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + if(name.equalsIgnoreCase(methodName) && methodDesc.equalsIgnoreCase(paramAndReturnType)){ + method = m; + } + } + return method; + } + + public Method getMainMethod() { + Method method = null; + for(Method m : methods){ + String name = pool.getUTF8String(m.getNameIndex()); + if(name.equalsIgnoreCase("main")){ + method = m; + } + } + return method; + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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(); + } + + + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..4006ca69e1 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.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(getReadableCodeText()); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode.toUpperCase()); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/CommandParser.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..e86d3de1de --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,144 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +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) { + if (codes == null || codes.length() <= 0) { + throw new RuntimeException("字节码指令解析错误!"); + } + List cmds = new ArrayList(); + CommandIterator iter = new CommandIterator(codes); + while (iter.hasNext()) { + String opcmd = iter.next2CharAsString(); + System.out.println("opcmd:" + opcmd); + if (bipush.equalsIgnoreCase(opcmd)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opcmd); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getfield.equalsIgnoreCase(opcmd)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equalsIgnoreCase(opcmd)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokespecial.equalsIgnoreCase(opcmd)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokevirtual.equalsIgnoreCase(opcmd)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equalsIgnoreCase(opcmd)) { + LdcCmd cmd = new LdcCmd(clzFile, opcmd); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (new_object.equalsIgnoreCase(opcmd)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equalsIgnoreCase(opcmd)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opcmd); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equalsIgnoreCase(opcmd) || aload_0.equalsIgnoreCase(opcmd) || aload_1.equalsIgnoreCase(opcmd) + || aload_2.equalsIgnoreCase(opcmd) || iload_1.equalsIgnoreCase(opcmd) + || iload_2.equalsIgnoreCase(opcmd) || iload_3.equalsIgnoreCase(opcmd) + || fload_3.equalsIgnoreCase(opcmd) || voidreturn.equalsIgnoreCase(opcmd) + || astore_1.equalsIgnoreCase(opcmd)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, opcmd); + cmds.add(cmd); + } else { + throw new RuntimeException("暂不支持的指令类型!"); + } + } + calcuateOffset(cmds); + 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; + } + + 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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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); + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.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); + } + + + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java index 2418beda19..091ecc2209 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java @@ -3,6 +3,7 @@ import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; @@ -69,4 +70,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { } return method; } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java b/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..14407bacbe --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; + +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.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/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java b/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..028161adc7 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java index 52e1eaffc3..b2128a5372 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java @@ -9,6 +9,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; @@ -223,7 +227,7 @@ public void testMethods(){ System.out.println("methods_size:"+methods.size()); { - Method m = methods.get(0); + Method m = methods.get(0); assertMethodEquals(pool,m, "", "(Ljava/lang/String;I)V", @@ -270,5 +274,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); + } } From 0030da65a68bbe07728806eadad0160aed33eb19 Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Wed, 19 Apr 2017 20:02:13 +0800 Subject: [PATCH 067/151] add count --- group17/article/20170409-20170416.md | 56 ++++++++++++++++++++++++++++ group17/article/template.md | 2 +- group17/count/homework.md | 3 +- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 group17/article/20170409-20170416.md diff --git a/group17/article/20170409-20170416.md b/group17/article/20170409-20170416.md new file mode 100644 index 0000000000..3d45ad0516 --- /dev/null +++ b/group17/article/20170409-20170416.md @@ -0,0 +1,56 @@ +# 自由写作 + +## 须知 +--- + +交作业时请在QQ 号后面填上各自的文章链接, 比如: + +51075907 http://m.blog.csdn.net/article/details?id=57083764 + +## 文章 +--- + +1204187480 + +102228177 + +876385982 + +785396327 + +1059107701 + +240094626 + +82427129 + +296910598 + +1264835468 + +516886559 + +1282579502 + +614982500 + +865797761 + +1540186032 + +176653813 + +116665530 + +51075907 + +1158154002 + +345450234 + +919764878 + +1368331120 + +517970312 + diff --git a/group17/article/template.md b/group17/article/template.md index 0b06ef733e..3d45ad0516 100644 --- a/group17/article/template.md +++ b/group17/article/template.md @@ -12,7 +12,7 @@ 1204187480 -102228177 http://note.youdao.com/noteshare?id=1f8f4a9d861e24948cdf0219a0d39f4e +102228177 876385982 diff --git a/group17/count/homework.md b/group17/count/homework.md index 640cf4698f..9422c2f12c 100644 --- a/group17/count/homework.md +++ b/group17/count/homework.md @@ -18,6 +18,7 @@ * [20170305-20170312](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170305-20170312.md) * [20170326-20170402](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170326-20170402.md) + * [20170402-20170409](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170402-20170409.md) -20170326-20170402.md 20170402-20170409.md + * [20170409-20170416](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170409-20170416.md) From 1f4be5bc40c4d707984520db027f56059ac8bd56 Mon Sep 17 00:00:00 2001 From: zheng <765324639@qq.com> Date: Wed, 19 Apr 2017 20:55:31 +0800 Subject: [PATCH 068/151] =?UTF-8?q?=E5=AE=8C=E6=88=90jvm=E7=AC=AC=E5=9B=9B?= =?UTF-8?q?=E6=AC=A1=E4=BD=9C=E4=B8=9A=E4=B8=AD=E7=9A=84jvm=E9=83=A8?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/minijvm/attr/CodeAttr.java | 103 ++++++----- .../java/minijvm/attr/LocalVariableTable.java | 13 ++ .../src/main/java/minijvm/clz/ClassFile.java | 175 ++++++++++-------- .../src/main/java/minijvm/cmd/BiPushCmd.java | 21 +++ .../java/minijvm/cmd/ByteCodeCommand.java | 129 +++++++++++++ .../main/java/minijvm/cmd/CommandParser.java | 158 ++++++++++++++++ .../main/java/minijvm/cmd/GetFieldCmd.java | 21 +++ .../java/minijvm/cmd/GetStaticFieldCmd.java | 19 ++ .../java/minijvm/cmd/InvokeSpecialCmd.java | 21 +++ .../java/minijvm/cmd/InvokeVirtualCmd.java | 21 +++ .../src/main/java/minijvm/cmd/LdcCmd.java | 29 +++ .../main/java/minijvm/cmd/NewObjectCmd.java | 19 ++ .../main/java/minijvm/cmd/NoOperandCmd.java | 24 +++ .../main/java/minijvm/cmd/OneOperandCmd.java | 28 +++ .../main/java/minijvm/cmd/PutFieldCmd.java | 19 ++ .../main/java/minijvm/cmd/TwoOperandCmd.java | 68 +++++++ .../java/minijvm/loader/ClassFileParser.java | 6 +- .../src/main/java/minijvm/method/Method.java | 108 ++++++----- .../java/minijvm/print/ClassFilePrinter.java | 45 +++++ .../minijvm/print/ConstantPoolPrinter.java | 18 ++ .../minijvm/loader/ClassFileloaderTest.java | 80 ++++++++ 21 files changed, 957 insertions(+), 168 deletions(-) create mode 100644 group01/765324639/src/main/java/minijvm/cmd/BiPushCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/ByteCodeCommand.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/CommandParser.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/OneOperandCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java create mode 100644 group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java create mode 100644 group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java diff --git a/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java index 0044adced8..43a02cfa48 100644 --- a/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java +++ b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java @@ -1,55 +1,68 @@ package minijvm.attr; import minijvm.clz.ClassFile; +import minijvm.cmd.ByteCodeCommand; +import minijvm.constant.ConstantPool; import minijvm.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 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; + } - //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 setLineNumberTable(LineNumberTable t) { - this.lineNumTable = t; - } + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + + return null; + } + - public void setLocalVariableTable(LocalVariableTable t) { - this.localVarTable = t; - } - - public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ - - - return null; - } - private void setStackMapTable(StackMapTable t) { - this.stackMapTable = t; - - } + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + //buffer.append("Code:").append(code).append("\n"); + for(int i=0;i fields = new ArrayList(); - private List methods = new ArrayList(); - - public ClassIndex getClzIndex() { - return clzIndex; - } - public AccessFlag getAccessFlag() { - return accessFlag; - } - public void setAccessFlag(AccessFlag accessFlag) { - this.accessFlag = accessFlag; - } - - - - public ConstantPool getConstantPool() { - return pool; - } - public int getMinorVersion() { - return minorVersion; - } - public void setMinorVersion(int minorVersion) { - this.minorVersion = minorVersion; - } - public int getMajorVersion() { - return majorVersion; - } - public void setMajorVersion(int majorVersion) { - this.majorVersion = majorVersion; - } - public void setConstPool(ConstantPool pool) { - this.pool = pool; - - } - public void setClassIndex(ClassIndex clzIndex) { - this.clzIndex = clzIndex; - } - - 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 print(){ - - if(this.accessFlag.isPublicClass()){ - System.out.println("Access flag : public "); - } - System.out.println("Class Name:"+ getClassName()); - - System.out.println("Super Class Name:"+ getSuperClassName()); - - - } - - private String getClassName(){ - int thisClassIndex = this.clzIndex.getThisClassIndex(); - ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); - return thisClass.getClassName(); - } - private String getSuperClassName(){ - ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); - return superClass.getClassName(); - } + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + public String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + public String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType){ + for (Method method : methods) { + if (pool.getUTF8String(method.getNameIndex()).equals(methodName) + && pool.getUTF8String(method.getDescriptorIndex()).equals(paramAndReturnType)) { + return method; + } + } + return null; + } + public Method getMainMethod(){ + return getMethod("main", "([Ljava/lang/String;)V"); + } } + diff --git a/group01/765324639/src/main/java/minijvm/cmd/BiPushCmd.java b/group01/765324639/src/main/java/minijvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..b2945d337f --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/BiPushCmd.java @@ -0,0 +1,21 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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(); + } + + + +} diff --git a/group01/765324639/src/main/java/minijvm/cmd/ByteCodeCommand.java b/group01/765324639/src/main/java/minijvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..910a59520f --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/ByteCodeCommand.java @@ -0,0 +1,129 @@ +package minijvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import minijvm.clz.ClassFile; +import minijvm.constant.ConstantInfo; +import minijvm.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(); + + + + + @Override + 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.toUpperCase()); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java b/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java new file mode 100644 index 0000000000..189c208e87 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java @@ -0,0 +1,158 @@ +package minijvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import minijvm.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) { + List commandList = new ArrayList<>(); + + CommandIterator iter = new CommandIterator(codes); + while (iter.hasNext()) { + String operCode = iter.next2CharAsString(); + if (aload_0.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (invokespecial.equalsIgnoreCase(operCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, operCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (aload_1.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (putfield.equalsIgnoreCase(operCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, operCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (aload_2.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (ireturn.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (voidreturn.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (getstatic.equalsIgnoreCase(operCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, operCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (ldc.equalsIgnoreCase(operCode)) { + LdcCmd cmd = new LdcCmd(clzFile, operCode); + cmd.setOperand(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (invokevirtual.equalsIgnoreCase(operCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, operCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (new_object.equalsIgnoreCase(operCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, operCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (dup.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (bipush.equalsIgnoreCase(operCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, operCode); + cmd.setOperand(iter.next2CharAsInt()); + commandList.add(cmd); + } else if (astore_1.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (iload_1.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else if (iload_2.equalsIgnoreCase(operCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, operCode); + commandList.add(cmd); + } else { + throw new RuntimeException("未实现的操作码:" + operCode); + } + } + calcuateOffset(commandList); + ByteCodeCommand[] commands = new ByteCodeCommand[commandList.size()]; + return commandList.toArray(commands); + } + + 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(); + } + + public void nextLengthByte(int length) { + pos += (length * 2); + } + + } +} diff --git a/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..972ae719be --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java @@ -0,0 +1,21 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..648a8940ec --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,19 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java b/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..460706b635 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,21 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java b/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..b2957bbcb6 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,21 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java b/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..b6ca03f4ac --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.constant.ConstantInfo; +import minijvm.constant.ConstantPool; +import minijvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = 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/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java b/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..aaff3aecef --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java b/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..e9a3493426 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java @@ -0,0 +1,24 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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(); + } + + + + @Override + public int getLength(){ + return 1; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/cmd/OneOperandCmd.java b/group01/765324639/src/main/java/minijvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..bf2d567850 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package minijvm.cmd; + +import minijvm.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; + + } + @Override + public int getLength(){ + return 2; + } + + +} diff --git a/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..ae41b17fde --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java b/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..262bedc338 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java @@ -0,0 +1,68 @@ +package minijvm.cmd; + +import minijvm.clz.ClassFile; +import minijvm.constant.ClassInfo; +import minijvm.constant.ConstantInfo; +import minijvm.constant.ConstantPool; +import minijvm.constant.FieldRefInfo; +import minijvm.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(); + } + @Override + public int getLength(){ + return 3; + } +} diff --git a/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java b/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java index cb42be22d6..9318165708 100644 --- a/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java +++ b/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java @@ -10,6 +10,8 @@ import minijvm.clz.AccessFlag; import minijvm.clz.ClassFile; import minijvm.clz.ClassIndex; +import minijvm.cmd.ByteCodeCommand; +import minijvm.cmd.CommandParser; import minijvm.constant.ClassInfo; import minijvm.constant.ConstantInfo; import minijvm.constant.ConstantPool; @@ -212,7 +214,9 @@ private CodeAttr parseCodeAttribute(ByteCodeIterator iter, ClassFile classFile) int codeLength = iter.nextU4ToInt(); String code = iter.nextUxToHexString(codeLength); - CodeAttr codeAttr = new CodeAttr(nameIndex, length, maxStack, maxLocals, codeLength, code); + ByteCodeCommand[] codeCommands = CommandParser.parse(classFile, code); + + CodeAttr codeAttr = new CodeAttr(nameIndex, length, maxStack, maxLocals, codeLength, code, codeCommands); // TODO Code属性中的exception int exceptionLength = iter.nextU2ToInt(); diff --git a/group01/765324639/src/main/java/minijvm/method/Method.java b/group01/765324639/src/main/java/minijvm/method/Method.java index 3d0b9a5678..248c3e79f1 100644 --- a/group01/765324639/src/main/java/minijvm/method/Method.java +++ b/group01/765324639/src/main/java/minijvm/method/Method.java @@ -2,53 +2,77 @@ import minijvm.attr.CodeAttr; import minijvm.clz.ClassFile; +import minijvm.cmd.ByteCodeCommand; +import minijvm.constant.ConstantPool; +import minijvm.constant.UTF8Info; import minijvm.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; - } + + 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 int getNameIndex() { - return nameIndex; - } - public int getDescriptorIndex() { - return descriptorIndex; - } - - public CodeAttr getCodeAttr() { - return codeAttr; - } + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + - 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 Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { - this.clzFile = clzFile; - this.accessFlag = accessFlag; - this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; - } + + + + + @Override + 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){ + return null; + + } - - - - - public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ - return null; - - } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java b/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..c5c4898b29 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package minijvm.print; + +import minijvm.clz.ClassFile; +import minijvm.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) throws ClassNotFoundException{ + 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/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java b/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..573b4e8e46 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java @@ -0,0 +1,18 @@ +package minijvm.print; + +import minijvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java b/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java index 80586f51e2..625d22e4f2 100644 --- a/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java +++ b/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java @@ -10,6 +10,10 @@ import minijvm.clz.ClassFile; import minijvm.clz.ClassIndex; +import minijvm.cmd.BiPushCmd; +import minijvm.cmd.ByteCodeCommand; +import minijvm.cmd.OneOperandCmd; +import minijvm.cmd.TwoOperandCmd; import minijvm.constant.ClassInfo; import minijvm.constant.ConstantPool; import minijvm.constant.MethodRefInfo; @@ -270,5 +274,81 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } + + //-----第四次JVM作业----- + + @Test + public void testByteCodeCommand(){ + { + Method initMethod = 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 = 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 = 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 = 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 02a464b518276d6ab4d3aa194dafb96fe4f55ba7 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 19 Apr 2017 23:36:52 +0800 Subject: [PATCH 069/151] =?UTF-8?q?=E5=90=8E=E5=89=8D=E7=BC=80=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExpr.java | 19 +-- .../basic/stack/expr/InfixToPostfix.java | 67 +++++++++ .../basic/stack/expr/InfixToPostfixTest.java | 32 +++++ .../basic/stack/expr/PostfixExpr.java | 35 +++++ .../basic/stack/expr/PostfixExprTest.java | 41 ++++++ .../basic/stack/expr/PrefixExpr.java | 36 +++++ .../basic/stack/expr/PrefixExprTest.java | 44 ++++++ .../coding2017/basic/stack/expr/Token.java | 64 +++++++++ .../basic/stack/expr/TokenParser.java | 57 ++++++++ .../basic/stack/expr/TokenParserTest.java | 41 ++++++ .../coding2017/minijvm/attr/CodeAttr.java | 24 +++- .../minijvm/attr/LineNumberTable.java | 12 +- .../minijvm/attr/LocalVariableTable.java | 15 +- .../coding2017/minijvm/clz/ClassFile.java | 13 +- .../coding2017/minijvm/cmd/BiPushCmd.java | 21 +++ .../minijvm/cmd/ByteCodeCommand.java | 132 ++++++++++++++++++ .../coding2017/minijvm/cmd/CommandParser.java | 84 +++++++++++ .../coding2017/minijvm/cmd/GetFieldCmd.java | 21 +++ .../minijvm/cmd/GetStaticFieldCmd.java | 19 +++ .../minijvm/cmd/InvokeSpecialCmd.java | 21 +++ .../minijvm/cmd/InvokeVirtualCmd.java | 21 +++ .../coding2017/minijvm/cmd/LdcCmd.java | 29 ++++ .../coding2017/minijvm/cmd/NewObjectCmd.java | 19 +++ .../coding2017/minijvm/cmd/NoOperandCmd.java | 23 +++ .../coding2017/minijvm/cmd/OneOperandCmd.java | 29 ++++ .../coding2017/minijvm/cmd/PutFieldCmd.java | 19 +++ .../coding2017/minijvm/cmd/TwoOperandCmd.java | 67 +++++++++ .../coding2017/minijvm/method/Method.java | 4 + .../minijvm/print/ClassFilePrinter.java | 45 ++++++ .../minijvm/print/ConstantPoolPrinter.java | 18 +++ .../minijvm/test/ClassFileloaderTest.java | 77 ++++++++++ 31 files changed, 1121 insertions(+), 28 deletions(-) create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixToPostfix.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixToPostfixTest.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PostfixExpr.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PostfixExprTest.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PrefixExpr.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PrefixExprTest.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/Token.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParser.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParserTest.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/BiPushCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/ByteCodeCommand.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/OneOperandCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/TwoOperandCmd.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java create mode 100644 group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java index 1e597a2b24..87344ca452 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java @@ -33,7 +33,7 @@ private void manageMultiAndDivOper(String[] elements,Stack numStack,Stack operSt preElement = (Float)numStack.pop(); i++; nextElement = Float.valueOf(elements[i]); - numStack.push(doBaseOper(preElement,nextElement,elements[i-1])); + numStack.push(Token.doBaseOper(preElement,nextElement,elements[i-1])); } } } @@ -42,27 +42,12 @@ private void manageMultiAndDivOper(String[] elements,Stack numStack,Stack operSt private float manageAddAndMinusOper(Stack numStack,Stack operStack){ float result = 0f;; while(!operStack.isEmpty()){ - result = doBaseOper(result,(Float)numStack.pop(),(String)operStack.pop()); + result = Token.doBaseOper(result,(Float)numStack.pop(),(String)operStack.pop()); } result += (Float)numStack.pop(); return result; } - private float doBaseOper(float preData,float nextData,String oper){ - switch(oper){ - case "+": - return preData+nextData; - case "-": - return preData-nextData; - case "*": - return preData*nextData; - case "/": - return preData/nextData; - default: - throw new RuntimeException("could not recognise oper:"+oper); - } - } - public String[] getElementArray(String expression){ char[] charArray = expression.toCharArray(); StringBuffer stringBuffer = new StringBuffer(); diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..d444fef039 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,67 @@ +package com.github.ipk2015.coding2017.basic.stack.expr; + + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + int len = expr.length(); + char c,temp; + Stack stack = new Stack(); + StringBuffer buffer = new StringBuffer(); + for(int i = 0;i tokens = InfixToPostfix.convert("3+(2-5)*6/3"); + + Assert.assertEquals(3, tokens.get(0).getIntValue()); + Assert.assertEquals(2, tokens.get(1).getIntValue()); + Assert.assertEquals(5, tokens.get(2).getIntValue()); + Assert.assertEquals("-", tokens.get(3).toString()); + Assert.assertEquals(6, tokens.get(4).getIntValue()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(3, tokens.get(6).getIntValue()); + Assert.assertEquals("/", tokens.get(7).toString()); + Assert.assertEquals("+", tokens.get(8).toString()); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PostfixExpr.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..af427fa948 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,35 @@ +package com.github.ipk2015.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() { + TokenParser parser = new TokenParser(); + List list = parser.parse(expr); + + Stack stack = new Stack(); + int len = list.size(); + float preNum,afterNum; + Token token; + for(int i = 0;i list = parser.parse(expr); + + Stack stack = new Stack(); + int len = list.size(); + float preNum,afterNum; + Token token; + 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; + } + + public static float doBaseOper(float preData,float nextData,String oper){ + switch(oper){ + case "+": + return preData+nextData; + case "-": + return preData-nextData; + case "*": + return preData*nextData; + case "/": + return preData/nextData; + default: + throw new RuntimeException("could not recognise oper:"+oper); + } + } + + +} \ No newline at end of file diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParser.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..998d1e4c8e --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.github.ipk2015.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/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParserTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..2543baec60 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.github.ipk2015.coding2017.basic.stack.expr; + +import static org.junit.Assert.*; + +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()); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java index 2f141a20a3..ff7fcc4294 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.github.ipk2015.coding2017.minijvm.attr; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.cmd.ByteCodeCommand; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo { @@ -12,10 +14,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; @@ -26,7 +28,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) { @@ -78,7 +80,17 @@ private static void addSonAttr(ClassFile clzFile,CodeAttr codeAttr,ByteCodeItera } } - + 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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java new file mode 100644 index 0000000000..23b2859e6a --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java @@ -0,0 +1,84 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import java.util.List; + +import com.github.ipk2015.coding2017.minijvm.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(); + } + + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..ad694d7eec --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java @@ -0,0 +1,21 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..87bfca3c7f --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,19 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..e573129d76 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,21 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..989c3f6fae --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,21 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..bc72a9f300 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..973061d110 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..62c51c2b3a --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/OneOperandCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..ca6052b34c --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/OneOperandCmd.java @@ -0,0 +1,29 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + + + +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..e73ff203d5 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/TwoOperandCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..99c6b99455 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.github.ipk2015.coding2017.minijvm.cmd; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java index 3298a36d6b..61b91fa7b9 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java @@ -3,6 +3,7 @@ import com.github.ipk2015.coding2017.minijvm.attr.AttributeInfo; import com.github.ipk2015.coding2017.minijvm.attr.CodeAttr; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.cmd.ByteCodeCommand; import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator; public class Method { @@ -67,4 +68,7 @@ private static void addAttr(ClassFile clzFile,Method method,ByteCodeIterator ite throw new RuntimeException("方法的此属性不存在:"+attrName); } } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..6615a189f5 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package com.github.ipk2015.coding2017.minijvm.print; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..295c509941 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java @@ -0,0 +1,18 @@ +package com.github.ipk2015.coding2017.minijvm.print; + +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java index 0a3979119d..213046188c 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java @@ -12,6 +12,10 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.clz.ClassIndex; +import com.github.ipk2015.coding2017.minijvm.cmd.BiPushCmd; +import com.github.ipk2015.coding2017.minijvm.cmd.ByteCodeCommand; +import com.github.ipk2015.coding2017.minijvm.cmd.OneOperandCmd; +import com.github.ipk2015.coding2017.minijvm.cmd.TwoOperandCmd; import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; @@ -279,5 +283,78 @@ 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); + } } From bf87a113995ff79ee34866dea233a41b68d0c1ef Mon Sep 17 00:00:00 2001 From: johnChnia Date: Thu, 20 Apr 2017 01:23:21 +0800 Subject: [PATCH 070/151] =?UTF-8?q?=E5=AE=8C=E6=88=90prefix,postfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExpr.java | 15 +++++ .../basic/stack/expr/InfixExprTest.java | 52 +++++++++++++++++ .../basic/stack/expr/InfixToPostfix.java | 14 +++++ .../coding2017/basic/stack/expr/Operator.java | 41 +++++++++++++ .../basic/stack/expr/PostfixExpr.java | 27 +++++++++ .../basic/stack/expr/PostfixExprTest.java | 41 +++++++++++++ .../basic/stack/expr/PrefixExpr.java | 25 ++++++++ .../basic/stack/expr/PrefixExprTest.java | 45 ++++++++++++++ .../coding2017/basic/stack/expr/Token.java | 50 ++++++++++++++++ .../basic/stack/expr/TokenParser.java | 58 +++++++++++++++++++ .../basic/stack/expr/TokenParserTest.java | 39 +++++++++++++ 11 files changed, 407 insertions(+) create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java create mode 100644 group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..ddafe58c46 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java @@ -0,0 +1,15 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..e47a8841da --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..f42f73282a --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,14 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java new file mode 100644 index 0000000000..52ff15fa80 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java @@ -0,0 +1,41 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.stack.Stack; + +/** + * Created by john on 2017/4/20. + */ +public class Operator { + + public void handlerToken(String fix, Stack stack, Token token) { + if (token.isNumber()) { + stack.push(Float.parseFloat(token.toString())); + } else if (token.isOperator()) { + float p = stack.pop(); + float q = stack.pop(); + stack.push(perform(fix, token.toString(), p, q)); + } + } + + private float perform(String fix, String operator, float p, float q) { + float result = 0.0f; + if (operator.equals("+")) { + result = p + q; + } else if (operator.equals("-")) { + if (fix.equals("postfix")) { + result = q - p; + } else if (fix.equals("prefix")){ + result = p - q; + } + } else if (operator.equals("*")) { + result = p * q; + } else if (operator.equals("/")) { + if (fix.equals("postfix")) { + result = q / p; + } else if (fix.equals("prefix")){ + result = p / q; + } + } + return result; + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..dfecd16ed4 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,27 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(this.expr); + Operator operator = new Operator(); + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + operator.handlerToken("postfix", stack, tokens.get(i)); + + } + + return stack.pop(); + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..312eed28b3 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.johnChnia.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/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..c16f529845 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,25 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(this.expr); + Operator operator = new Operator(); + Stack stack = new Stack<>(); + for (int i = tokens.size() - 1; i >= 0; i--) { + operator.handlerToken("prefix", stack, tokens.get(i)); + } + return stack.pop(); + } + + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..30f67b2710 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.johnChnia.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/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java new file mode 100644 index 0000000000..f87a210587 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.johnChnia.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 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/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..b9c8b80444 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java @@ -0,0 +1,58 @@ +package com.johnChnia.coding2017.basic.stack.expr; + + +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.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/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..cdb3b091db --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.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()); + } + +} From cc76d7c021f4928fa7c1548f2dfde107f02e8de5 Mon Sep 17 00:00:00 2001 From: earlywusa Date: Wed, 19 Apr 2017 10:42:49 -0700 Subject: [PATCH 071/151] Update 20170402-20170409.md --- group17/article/20170402-20170409.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170402-20170409.md b/group17/article/20170402-20170409.md index f0d32f145f..59e3477528 100644 --- a/group17/article/20170402-20170409.md +++ b/group17/article/20170402-20170409.md @@ -30,7 +30,7 @@ 516886559 -1282579502 https://www.evernote.com/l/AZ3ajLOAlTVHw7foK2KLb-bWZ7kw6FjljDA +1282579502 614982500 From 65ea9b2de442440d761a8b634e9b78ac2a183ebd Mon Sep 17 00:00:00 2001 From: Ren650119726 <102228177@qq.com> Date: Thu, 20 Apr 2017 08:56:55 +0800 Subject: [PATCH 072/151] =?UTF-8?q?=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/article/20170409-20170416.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group17/article/20170409-20170416.md b/group17/article/20170409-20170416.md index 3d45ad0516..eae67d9c31 100644 --- a/group17/article/20170409-20170416.md +++ b/group17/article/20170409-20170416.md @@ -12,7 +12,7 @@ 1204187480 -102228177 +102228177 http://note.youdao.com/noteshare?id=7a1c457bc3de9a140f4e077f6352fc11 876385982 From b22edf148d67c1e63b789dad35bb0b2750e6624b Mon Sep 17 00:00:00 2001 From: zheng <765324639@qq.com> Date: Thu, 20 Apr 2017 12:39:08 +0800 Subject: [PATCH 073/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E6=B1=A0=E9=83=A8=E5=88=86=EF=BC=88=E6=A8=A1?= =?UTF-8?q?=E4=BB=BFjavap=E6=8C=87=E4=BB=A4=E6=89=93=E5=8D=B0=E7=9A=84?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/minijvm/constant/ClassInfo.java | 4 + .../java/minijvm/constant/ConstantInfo.java | 68 +++++++++----- .../java/minijvm/constant/ConstantPool.java | 43 +++++---- .../java/minijvm/constant/FieldRefInfo.java | 4 + .../java/minijvm/constant/MethodRefInfo.java | 5 + .../minijvm/constant/NameAndTypeInfo.java | 5 + .../minijvm/constant/NullConstantInfo.java | 5 + .../java/minijvm/constant/StringInfo.java | 5 + .../main/java/minijvm/constant/UTF8Info.java | 66 +++++++------ .../java/minijvm/print/ClassFilePrinter.java | 80 ++++++++-------- .../minijvm/print/ConstantPoolPrinter.java | 11 ++- .../java/minijvm/print/JavapPrintVisitor.java | 93 +++++++++++++++++++ 12 files changed, 274 insertions(+), 115 deletions(-) create mode 100644 group01/765324639/src/main/java/minijvm/print/JavapPrintVisitor.java diff --git a/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java b/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java index c856052998..9baacbdffd 100644 --- a/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java @@ -22,4 +22,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/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java b/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java index 5fa0be0189..d40afea29b 100644 --- a/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java @@ -1,29 +1,47 @@ package minijvm.constant; public abstract class ConstantInfo { - public static final int UTF8_INFO = 1; - public static final int FLOAT_INFO = 4; - public static final int CLASS_INFO = 7; - public static final int STRING_INFO = 8; - public static final int FIELD_INFO = 9; - public static final int METHOD_INFO = 10; - public static final int NAME_AND_TYPE_INFO = 12; - protected ConstantPool constantPool; - - public ConstantInfo(){ - - } - - public ConstantInfo(ConstantPool pool) { - this.constantPool = pool; - } - public abstract int getType(); - - public ConstantPool getConstantPool() { - return constantPool; - } - public ConstantInfo getConstantInfo(int index){ - return this.constantPool.getConstantInfo(index); - } - + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo() { + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + + 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); + + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java b/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java index 12746a1f3c..6cd94a48d4 100644 --- a/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java +++ b/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java @@ -4,26 +4,25 @@ import java.util.List; public class ConstantPool { - - private List constantInfos = new ArrayList(); - - - public ConstantPool(){ - - } - public void addConstantInfo(ConstantInfo info){ - - this.constantInfos.add(info); - - } - - public ConstantInfo getConstantInfo(int index){ - return this.constantInfos.get(index); - } - public String getUTF8String(int index){ - return ((UTF8Info)this.constantInfos.get(index)).getValue(); - } - public Object getSize() { - return this.constantInfos.size() -1; - } + + private List constantInfos = new ArrayList(); + + + public ConstantPool() {} + + public void addConstantInfo(ConstantInfo info) { + this.constantInfos.add(info); + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantInfos.get(index); + } + + public String getUTF8String(int index) { + return ((UTF8Info) this.constantInfos.get(index)).getValue(); + } + + public int getSize() { + return this.constantInfos.size() - 1; + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java b/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java index ddcf2df456..e7a33ddc10 100644 --- a/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java @@ -53,4 +53,8 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java b/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java index f4c2368228..a731895413 100644 --- a/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java @@ -51,6 +51,11 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } diff --git a/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java b/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java index de88422d82..27690de3f7 100644 --- a/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java @@ -44,4 +44,9 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java b/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java index 88eb702f4b..09f5c4f280 100644 --- a/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java @@ -9,5 +9,10 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + // 占位类,不需访问 + throw new RuntimeException("此类不应访问到,代码中应该有问题"); + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/StringInfo.java b/group01/765324639/src/main/java/minijvm/constant/StringInfo.java index 915652a93c..21d586fad9 100644 --- a/group01/765324639/src/main/java/minijvm/constant/StringInfo.java +++ b/group01/765324639/src/main/java/minijvm/constant/StringInfo.java @@ -24,5 +24,10 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + } } diff --git a/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java b/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java index 1af71e8e9c..8b90c8e5fb 100644 --- a/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java +++ b/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java @@ -1,33 +1,43 @@ package minijvm.constant; -public class UTF8Info extends ConstantInfo{ - private int type = ConstantInfo.UTF8_INFO; - private int length ; - private String value; - public UTF8Info(ConstantPool pool) { - super(pool); - } - public int getLength() { - return length; - } - public void setLength(int length) { - this.length = length; - } - @Override +public class UTF8Info extends ConstantInfo { + private int type = ConstantInfo.UTF8_INFO; + private int length; + private String value; + + public UTF8Info(ConstantPool pool) { + super(pool); + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + @Override public int getType() { - return type; - } - @Override - public String toString() { - return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; - } - public String getValue() { - return value; - } - public void setValue(String value) { - this.value = value; - } - - + return type; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + ")]"; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } } diff --git a/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java b/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java index c5c4898b29..6ca5063b8b 100644 --- a/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java +++ b/group01/765324639/src/main/java/minijvm/print/ClassFilePrinter.java @@ -1,45 +1,49 @@ package minijvm.print; +import java.io.File; + import minijvm.clz.ClassFile; +import minijvm.constant.ConstantInfo.Visitor; import minijvm.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) throws ClassNotFoundException{ - 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(); - } + ClassFile clzFile = null; + + public ClassFilePrinter(ClassFile clzFile) { + this.clzFile = clzFile; + } + + public void print(Visitor visitor) { + + 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.getMajorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(visitor); + + + + } + + public static void main(String[] args) throws ClassNotFoundException { + String path = new File(".", "target\\test-classes").getAbsolutePath(); + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "minijvm.loader.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + Visitor visitor = new JavapPrintVisitor(); + printer.print(visitor); + } } diff --git a/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java b/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java index 573b4e8e46..34ce6ba488 100644 --- a/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java +++ b/group01/765324639/src/main/java/minijvm/print/ConstantPoolPrinter.java @@ -1,5 +1,7 @@ package minijvm.print; +import minijvm.constant.ConstantInfo; +import minijvm.constant.ConstantInfo.Visitor; import minijvm.constant.ConstantPool; public class ConstantPoolPrinter { @@ -7,11 +9,16 @@ public class ConstantPoolPrinter { ConstantPoolPrinter(ConstantPool pool){ this.pool = pool; } - public void print(){ + public void print(Visitor visitor){ System.out.println("Constant Pool:"); - + int size = pool.getSize(); + System.out.println("size:" + size); + for (int i = 1; i <= size; i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + constantInfo.accept(visitor); + } } diff --git a/group01/765324639/src/main/java/minijvm/print/JavapPrintVisitor.java b/group01/765324639/src/main/java/minijvm/print/JavapPrintVisitor.java new file mode 100644 index 0000000000..f080171ebc --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/print/JavapPrintVisitor.java @@ -0,0 +1,93 @@ +package minijvm.print; + +import minijvm.constant.ClassInfo; +import minijvm.constant.ConstantInfo.Visitor; +import minijvm.constant.FieldRefInfo; +import minijvm.constant.MethodRefInfo; +import minijvm.constant.NameAndTypeInfo; +import minijvm.constant.StringInfo; +import minijvm.constant.UTF8Info; + +public class JavapPrintVisitor implements Visitor{ + + private int index = 1; + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("Class")) + .append("#" + info.getUtf8Index()); + System.out.println(builder.toString()); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("Fieldref")) + .append("#" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + System.out.println(builder.toString()); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("Methodref")) + .append("#" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + System.out.println(builder.toString()); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("NameAndType")) + .append("#" + info.getIndex1() + ":#" + info.getIndex2()); + System.out.println(builder.toString()); + } + + @Override + public void visitString(StringInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("String")) + .append("#" + info.getIndex()); + System.out.println(builder.toString()); + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder builder = new StringBuilder(); + builder.append(getThisIndexOfPrefix(index++)) + .append(getMid("Utf8")) + .append(info.getValue()); + System.out.println(builder.toString()); + } + + private String getThisIndexOfPrefix(int index) { + if (index < 1) { + throw new IllegalArgumentException("错误的索引"); + } + + if (index < 10) { + return " #" + index + " = "; + } else if (index < 100) { + return " #" + index + " = "; + } else if (index < 1000) { + return " #" + index + " = "; + } else { + throw new IllegalArgumentException("还没有实现" + index + "个常量的打印"); + } + } + + private String getMid(String type) { + if (type.length() >= 19) { + return type; + } + String str = " "; + int length = type.length(); + return type + str.substring(length); + } +} From e334b646e9bcf342e7bf1bd2f3ef5190dab83d40 Mon Sep 17 00:00:00 2001 From: zj <2258659044@qq.com> Date: Thu, 20 Apr 2017 15:50:44 +0800 Subject: [PATCH 074/151] =?UTF-8?q?=E7=AC=AC=E5=9B=9B=E6=AC=A1jvm=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coderising/jvm/cmd/TwoOperandCmd.java | 2 - .../coding/basic/stack/expr/FixExprUtil.java | 81 -------- .../coding/basic/stack/expr/InfixExpr.java | 3 + .../basic/stack/expr/InfixToPostfix.java | 56 ------ .../coding/basic/stack/expr/PostfixExpr.java | 3 + .../coding/basic/stack/expr/PrefixExpr.java | 3 + .../stack/expr/{ => util}/ExprIterator.java | 3 +- .../basic/stack/expr/util/FixExprUtil.java | 174 ++++++++++++++++++ .../basic/stack/expr/{ => util}/Operator.java | 13 +- 9 files changed, 195 insertions(+), 143 deletions(-) delete mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java delete mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java rename group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/{ => util}/ExprIterator.java (86%) create mode 100644 group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/FixExprUtil.java rename group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/{ => util}/Operator.java (69%) diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java index 334eec9f98..6cb42d2a83 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -2,7 +2,6 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ClassInfo; -import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.MethodRefInfo; @@ -49,7 +48,6 @@ protected String getOperandAsClassInfo(ConstantPool pool){ 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/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java deleted file mode 100644 index 0477bce3ec..0000000000 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/FixExprUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.coding.basic.stack.expr; - -import com.coding.basic.List; -import com.coding.basic.array.ArrayList; - -public class FixExprUtil { - - /** - * 运算 - * @param a 数字 - * @param oper 运算符 - * @param b 数字 - * @return - */ - public static float calculate(float a,Operator oper,float b) { - - String operFlag = oper.getFlag(); - - float res = 0f; - if (Operator.ADD.getFlag().equals(operFlag)) { - res = a + b; - } else if (Operator.SUB.getFlag().equals(operFlag)) { - res = a - b; - } else if (Operator.MULTY.getFlag().equals(operFlag)) { - res = a * b; - } else if (Operator.DIVIDE.getFlag().equals(operFlag)) { - res = a / b; - } - return res; - } - - /** - * 将字符串顺序逆置 - * @param str - * @return - */ - public static String reverse(String expr){ - - return new StringBuffer(expr).reverse().toString(); - } - - /** - * 将表达式字符串转换为List - * @param expr - * @return - */ - public static List FixExprToArray(String expr){ - - List ls = new ArrayList<>(); - - String[] strArr = expr.split(" "); - for (String str : strArr) { - parse(str,ls); - } - - return ls; - } - - public static void parse(String str,List ls){ - - char[] chr = str.toCharArray(); - StringBuilder token = new StringBuilder(); - - for (char c : chr) { - if(Operator.contains(c+"")){ - if(!"".equals(token.toString())){ - ls.add(token.toString()); - token = new StringBuilder(); - } - ls.add(c+""); - }else{ - token.append(c); - } - } - if(!"".equals(token.toString())){ - ls.add(token.toString()); - } - - } - -} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java index 0ee14605fc..a02d03c861 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixExpr.java @@ -2,6 +2,9 @@ import com.coding.basic.stack.Stack; import com.coding.basic.stack.StackUtil; +import com.coding.basic.stack.expr.util.ExprIterator; +import com.coding.basic.stack.expr.util.FixExprUtil; +import com.coding.basic.stack.expr.util.Operator; public class InfixExpr { diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java deleted file mode 100644 index 02aa5b5bff..0000000000 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/InfixToPostfix.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.coding.basic.stack.expr; - -import com.coding.basic.stack.Stack; -import com.coding.basic.stack.StackUtil; - -public class InfixToPostfix { - - public static String convert(String expr) { - - ExprIterator it = new ExprIterator(expr); - - Stack s1 = new Stack<>(); - - Stack s2 = new Stack<>(); - - int preLevel,thisLevel; - - while(it.hasNext()){ - - String element = it.next(); - if(Operator.contains(element)){//运算符 - while(true){ - if(s1.isEmpty()){ - s1.push(element); - break; - }else{ - preLevel = Operator.getLevelByFlag(s1.peek()); - thisLevel = Operator.getLevelByFlag(element); - if(thisLevel>preLevel){ - s1.push(element); - break; - }else{ - s2.push(s1.pop()); - } - } - } - }else{ - s2.push(element); - } - } - - while(!s1.isEmpty()){ - s2.push(s1.pop()); - } - StackUtil.reverse(s2); - return s2.toString(); - } - - public static void main(String[] args) { - - String a = "9+(3-1)*3+10/2"; - String post = InfixToPostfix.convert(a); - System.out.println(post); - - } -} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java index b406bc3ead..cdd7605635 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -1,6 +1,9 @@ package com.coding.basic.stack.expr; import com.coding.basic.stack.Stack; +import com.coding.basic.stack.expr.util.ExprIterator; +import com.coding.basic.stack.expr.util.FixExprUtil; +import com.coding.basic.stack.expr.util.Operator; public class PostfixExpr { diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java index a11e9a13ba..4a0b025cfe 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -1,6 +1,9 @@ package com.coding.basic.stack.expr; import com.coding.basic.stack.Stack; +import com.coding.basic.stack.expr.util.ExprIterator; +import com.coding.basic.stack.expr.util.FixExprUtil; +import com.coding.basic.stack.expr.util.Operator; public class PrefixExpr { diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/ExprIterator.java similarity index 86% rename from group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java rename to group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/ExprIterator.java index 513cc901fb..59efc0907d 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/ExprIterator.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/ExprIterator.java @@ -1,9 +1,8 @@ -package com.coding.basic.stack.expr; +package com.coding.basic.stack.expr.util; import com.coding.basic.List; import com.coding.basic.array.ArrayList; - /** * 表达式迭代器 * @author zj diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/FixExprUtil.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/FixExprUtil.java new file mode 100644 index 0000000000..4f431f219d --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/FixExprUtil.java @@ -0,0 +1,174 @@ +package com.coding.basic.stack.expr.util; + +import java.util.regex.Pattern; + +import com.coding.basic.List; +import com.coding.basic.array.ArrayList; +import com.coding.basic.stack.Stack; + +public class FixExprUtil { + + private static String LEFTBRACKRT= "("; + private static String RIGHTBRACKET= ")"; + + /** + * 运算 + * @param a 数字 + * @param oper 运算符 + * @param b 数字 + * @return + */ + public static float calculate(float a,Operator oper,float b) { + + String operFlag = oper.getFlag(); + + float res = 0f; + if (Operator.ADD.getFlag().equals(operFlag)) { + res = a + b; + } else if (Operator.SUB.getFlag().equals(operFlag)) { + res = a - b; + } else if (Operator.MULTY.getFlag().equals(operFlag)) { + res = a * b; + } else if (Operator.DIVIDE.getFlag().equals(operFlag)) { + res = a / b; + } + return res; + } + + /** + * 将字符串顺序逆置 + * @param str + * @return + */ + public static String reverse(String expr){ + + return new StringBuffer(expr).reverse().toString(); + } + + /** + * 判断字符串是否为数字 + * 注意:不包括小数 + * @param str + * @return + */ + public static boolean isNumeric(String str){ + Pattern pattern = Pattern.compile("[0-9]*"); + return pattern.matcher(str).matches(); + } + + /** + * 将中缀表达式装换为后缀表达式 + * @param expr + * @return + */ + public static String InfixCovertToPostfix(String expr){ + + ExprIterator it = new ExprIterator(expr); + Stack stack = new Stack<>(); + List postFixList = new ArrayList(); + + while(it.hasNext()){ + + String element = it.next(); + //数字直接输出 + if(FixExprUtil.isNumeric(element)){ + postFixList.add(element); + }else if(RIGHTBRACKET.equals(element)){//去除左右括号 + do { + postFixList.add(stack.pop()); + } while (!LEFTBRACKRT.equals(stack.pop())); + }else{ + int preLevel = 0; + int thisLevel = Operator.getLevelByFlag(element); + //当栈顶运算符优先级大于本次运算优先级时(左括号除外)出栈至栈顶优先级小于本次运算优先级 + while(preLevel>thisLevel&&preLevel!=3&&!stack.isEmpty()){ + String oprFlag = stack.pop(); + preLevel = Operator.getLevelByFlag(oprFlag); + postFixList.add(oprFlag); + } + stack.push(element); + } + + } + //将栈中剩余元素出栈 + while(!stack.isEmpty()){ + postFixList.add(stack.pop()); + } + //格式化输出 + StringBuffer postFix = new StringBuffer(); + for (int i = 0; i < postFixList.size(); i++) { + postFix.append(postFixList.get(i)+" "); + } + return postFix.toString(); + } + + /** + * 中缀表达式转前缀表达式 + * @param expr + * @return + */ + public static String InfixCovertToPrefix(String expr){ + + String post = InfixCovertToPostfix(expr); + return reverse(post); + } + + /** + * 后缀表达式转前缀表达式 + * @param expr + * @return + */ + public static String postfixCovertToPrefix(String expr){ + return reverse(expr); + } + + /** + * 前缀表达式转后缀表达式 + * @param expr + * @return + */ + public static String prefixCovertToPostfix(String expr){ + return reverse(expr); + } + + /** + * 将表达式字符串转换为List + * @param expr + * @return + */ + public static List FixExprToArray(String expr){ + + List ls = new ArrayList<>(); + + String[] strArr = expr.split(" "); + for (String str : strArr) { + parse(str,ls); + } + + return ls; + } + + public static void parse(String str,List ls){ + + char[] chr = str.toCharArray(); + StringBuilder token = new StringBuilder(); + + for (char c : chr) { + String element = String.valueOf(c); + if(Operator.contains(element)){ + if(!"".equals(token.toString())){ + ls.add(token.toString()); + token = new StringBuilder(); + } + ls.add(c+""); + }else{ + token.append(c); + } + } + if(!"".equals(token.toString())){ + ls.add(token.toString()); + } + + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/Operator.java similarity index 69% rename from group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java rename to group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/Operator.java index f6de250fc4..3e76c3b805 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/Operator.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/expr/util/Operator.java @@ -1,8 +1,9 @@ -package com.coding.basic.stack.expr; +package com.coding.basic.stack.expr.util; public enum Operator { - ADD("+",1),SUB("-",1),MULTY("*",2),DIVIDE("/",2); + ADD("+",1),SUB("-",1),MULTY("*",2),DIVIDE("/",2) + ,LEFTBRACKRT("(",3),RIGHTBRACKET(")",3); private String flag; private int level; @@ -33,6 +34,10 @@ public static Operator getOperator(String flag){ return MULTY; }else if(DIVIDE.flag.equals(flag)){ return DIVIDE; + }else if(LEFTBRACKRT.flag.equals(flag)){ + return LEFTBRACKRT; + }else if(RIGHTBRACKET.flag.equals(flag)){ + return RIGHTBRACKET; } return null; } @@ -47,6 +52,10 @@ public static boolean contains(String flag){ return true; }else if(DIVIDE.flag.equals(flag)){ return true; + }else if(LEFTBRACKRT.flag.equals(flag)){ + return true; + }else if(RIGHTBRACKET.flag.equals(flag)){ + return true; } return false; } From f2b5091074dc3673af9cd4cc64ca06dab3636e91 Mon Sep 17 00:00:00 2001 From: zj <2258659044@qq.com> Date: Thu, 20 Apr 2017 16:49:56 +0800 Subject: [PATCH 075/151] homework complete! --- .../jvm/print/ClassFilePrinter.java | 4 +- .../jvm/print/ConstantPoolPrinter.java | 43 ++++++++++++++----- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java index ee99162a4d..e0be352da4 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -14,11 +14,11 @@ public ClassFilePrinter(ClassFile clzFile){ public void print(){ if(clzFile.getAccessFlag().isPublicClass()){ - System.out.println("Access flag : public "); + System.out.println("Access flag:public "); } System.out.println("Class Name:"+ clzFile.getClassName()); - System.out.println("Super Class Name:"+ clzFile.getSuperClassName()); + System.out.println("Super ClassName:"+ clzFile.getSuperClassName()); System.out.println("minor version:" + clzFile.getMinorVersion()); diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java index 9abd6ca1ed..f2327a8029 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -24,7 +24,7 @@ public void print(){ @Override public void visitString(StringInfo info) { StringBuilder buffer = new StringBuilder(); - buffer.append("String #").append(info.getIndex()); + buffer.append(printConsName("string")).append("#"+info.getIndex()); System.out.println(buffer); } @@ -32,7 +32,7 @@ public void visitString(StringInfo info) { @Override public void visitNameAndType(NameAndTypeInfo info) { StringBuilder buffer = new StringBuilder(); - buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + buffer.append(printConsName("NameAndType")).append("#"+info.getIndex1()).append(":#") .append(info.getIndex2()); System.out.println(buffer); @@ -41,7 +41,7 @@ public void visitNameAndType(NameAndTypeInfo info) { @Override public void visitMethodRef(MethodRefInfo info) { StringBuilder buffer = new StringBuilder(); - buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + buffer.append(printConsName("MethodRef")).append("#"+info.getClassInfoIndex()).append(".#") .append(info.getNameAndTypeIndex()); System.out.println(buffer); @@ -50,7 +50,7 @@ public void visitMethodRef(MethodRefInfo info) { @Override public void visitFieldRef(FieldRefInfo info) { StringBuilder buffer = new StringBuilder(); - buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + buffer.append(printConsName("FieldRef")).append("#"+info.getClassInfoIndex()).append(".#") .append(info.getNameAndTypeIndex()); System.out.println(buffer); @@ -59,7 +59,7 @@ public void visitFieldRef(FieldRefInfo info) { @Override public void visitClassInfo(ClassInfo info) { StringBuilder buffer = new StringBuilder(); - buffer.append("Class #").append(info.getUtf8Index()) + buffer.append(printConsName("Class")).append("#"+info.getUtf8Index()) .append(" ").append(info.getClassName()); System.out.println(buffer); @@ -69,23 +69,44 @@ public void visitClassInfo(ClassInfo info) { @Override public void visistUTF8(UTF8Info info) { StringBuilder buffer = new StringBuilder(); - buffer.append("UTF8 ").append(info.getValue()); + buffer.append(printConsName("UTF8")).append(info.getValue()); System.out.println(buffer); } }; - for(int i=1; i<=pool.getSize(); i++){ + int size = pool.getSize(); + for(int i=1; i<=size; i++){ ConstantInfo constantInfo = pool.getConstantInfo(i); - System.out.print("#"+i+"="); + String space = genaralSpace(size,i); + System.out.print(space+"#"+i+"="); constantInfo.accept(visitor); } } - private void printSpaceAfterConsName(String consBeforStr){ + private String genaralSpace(int size,int i){ - String bashStr = (pool.getSize()+1)+"="+"NameAndType "; + int s1 = String.valueOf(size).length();//数字的位数 + int s2 = String.valueOf(i).length();//数字的位数 + StringBuffer str = new StringBuffer(); + for (int j = 0; j < s1-s2; j++) { + str.append(" "); + } + return str.toString(); + } + + /** + * 输出常量名称后面的空格 + * @param consBeforStr + */ + private String printConsName(String consName){ + + String bashStr = "NameAndType"; int bashLen = bashStr.length(); - int offset = bashLen-consBeforStr.length(); + int offset = bashLen-consName.length(); + for (int i = 0; i < offset; i++) { + consName+= " "; + } + return consName+" "; } } From 8e1a1ea91010bdff6d9bba53bacbb72239a0fc76 Mon Sep 17 00:00:00 2001 From: Haochen Date: Thu, 20 Apr 2017 17:21:10 +0800 Subject: [PATCH 076/151] move InfixExpr --- .../src/main/java/algorithm/{ => expression}/InfixExpr.java | 2 +- .../src/test/java/algorithm/{ => expression}/InfixExprTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename group01/895457260/code/src/main/java/algorithm/{ => expression}/InfixExpr.java (99%) rename group01/895457260/code/src/test/java/algorithm/{ => expression}/InfixExprTest.java (96%) diff --git a/group01/895457260/code/src/main/java/algorithm/InfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java similarity index 99% rename from group01/895457260/code/src/main/java/algorithm/InfixExpr.java rename to group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java index 1ddb740364..ad4fae505b 100644 --- a/group01/895457260/code/src/main/java/algorithm/InfixExpr.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java @@ -1,4 +1,4 @@ -package algorithm; +package algorithm.expression; import datastructure.basic.Stack; diff --git a/group01/895457260/code/src/test/java/algorithm/InfixExprTest.java b/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java similarity index 96% rename from group01/895457260/code/src/test/java/algorithm/InfixExprTest.java rename to group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java index 34480d6db7..e4c63b79f7 100644 --- a/group01/895457260/code/src/test/java/algorithm/InfixExprTest.java +++ b/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java @@ -1,4 +1,4 @@ -package algorithm; +package algorithm.expression; import org.junit.After; import org.junit.Assert; From cf675c2bf01efb2f79dc25920694e28ee375c7e0 Mon Sep 17 00:00:00 2001 From: Haochen Date: Thu, 20 Apr 2017 17:22:55 +0800 Subject: [PATCH 077/151] finish byte code command parsing --- .../java/jvm/command/CommandIterator.java | 29 +++++ .../main/java/jvm/command/CommandParser.java | 79 ++++++++++++ .../jvm/command/item/ByteCodeCommand.java | 117 ++++++++++++++++++ .../java/jvm/command/item/NoOperandCmd.java | 24 ++++ .../java/jvm/command/item/OneOperandCmd.java | 30 +++++ .../java/jvm/command/item/TwoOperandCmd.java | 74 +++++++++++ .../java/jvm/command/item/impl/ALoad0Cmd.java | 20 +++ .../java/jvm/command/item/impl/ALoad1Cmd.java | 20 +++ .../java/jvm/command/item/impl/ALoad2Cmd.java | 20 +++ .../java/jvm/command/item/impl/ALoad3Cmd.java | 20 +++ .../jvm/command/item/impl/AStore0Cmd.java | 20 +++ .../jvm/command/item/impl/AStore1Cmd.java | 20 +++ .../jvm/command/item/impl/AStore2Cmd.java | 20 +++ .../jvm/command/item/impl/AStore3Cmd.java | 20 +++ .../java/jvm/command/item/impl/BiPushCmd.java | 17 +++ .../java/jvm/command/item/impl/DupCmd.java | 20 +++ .../jvm/command/item/impl/GetFieldCmd.java | 20 +++ .../jvm/command/item/impl/GetStaticCmd.java | 19 +++ .../java/jvm/command/item/impl/ILoad0Cmd.java | 20 +++ .../java/jvm/command/item/impl/ILoad1Cmd.java | 20 +++ .../java/jvm/command/item/impl/ILoad2Cmd.java | 20 +++ .../java/jvm/command/item/impl/ILoad3Cmd.java | 20 +++ .../command/item/impl/InvokeSpecialCmd.java | 17 +++ .../command/item/impl/InvokeVirtualCmd.java | 17 +++ .../java/jvm/command/item/impl/LdcCmd.java | 27 ++++ .../java/jvm/command/item/impl/NewCmd.java | 19 +++ .../jvm/command/item/impl/PutFieldCmd.java | 18 +++ .../java/jvm/command/item/impl/ReturnCmd.java | 20 +++ 28 files changed, 787 insertions(+) create mode 100644 group01/895457260/code/src/main/java/jvm/command/CommandIterator.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/CommandParser.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/NoOperandCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/TwoOperandCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java create mode 100644 group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java diff --git a/group01/895457260/code/src/main/java/jvm/command/CommandIterator.java b/group01/895457260/code/src/main/java/jvm/command/CommandIterator.java new file mode 100644 index 0000000000..8fb8716c23 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/CommandIterator.java @@ -0,0 +1,29 @@ +package jvm.command; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class CommandIterator { + private String codes = null; + private int pos = 0; + + public 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); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/CommandParser.java b/group01/895457260/code/src/main/java/jvm/command/CommandParser.java new file mode 100644 index 0000000000..be794b07ed --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/CommandParser.java @@ -0,0 +1,79 @@ +package jvm.command; + +import jvm.classfile.ClassFile; +import jvm.command.item.ByteCodeCommand; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +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) { + String packageName = CommandParser.class.getPackage().getName() + ".item.impl."; + CommandIterator iterator = new CommandIterator(codes); + List commands = new ArrayList<>(); + try { + while (iterator.hasNext()) { + String opCode = iterator.next2CharAsString().toUpperCase(); + String cmdClassName = packageName + + ByteCodeCommand.codeMap.get(opCode).replaceAll("_", "") + + "Cmd"; + Class clazz = Class.forName(cmdClassName); + Constructor constructor = clazz.getConstructor( + ClassFile.class, String.class, CommandIterator.class); + + ByteCodeCommand command = (ByteCodeCommand) constructor.newInstance(clzFile, opCode, iterator); + commands.add(command); + } + } catch (ClassNotFoundException | NoSuchMethodException + | IllegalAccessException | InvocationTargetException | InstantiationException e) { + e.printStackTrace(); + } + calculateOffset(commands); + return commands.toArray(new ByteCodeCommand[commands.size()]); + } + + private static void calculateOffset(List commands) { + int offset = 0; + for (ByteCodeCommand cmd : commands) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java b/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java new file mode 100644 index 0000000000..b5276f526c --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java @@ -0,0 +1,117 @@ +package jvm.command.item; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; +import jvm.command.CommandIterator; + +import java.util.HashMap; +import java.util.Map; + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + public 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"); + } + + ByteCodeCommand(ClassFile clzFile, String opCode, CommandIterator iterator) { + this.clzFile = clzFile; + this.opCode = opCode; + initOperands(iterator); + } + + protected abstract void initOperands(CommandIterator iterator); + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + protected Constant 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() { + return opCode; + } + + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText() { + String txt = codeMap.get(opCode); + return txt == null ? opCode : txt.toLowerCase(); + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/NoOperandCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/NoOperandCmd.java new file mode 100644 index 0000000000..9ab8abd4b5 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/NoOperandCmd.java @@ -0,0 +1,24 @@ +package jvm.command.item; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; + +public abstract class NoOperandCmd extends ByteCodeCommand { + + public NoOperandCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + protected void initOperands(CommandIterator iterator) {} + + @Override + public String toString(ConstantPool pool) { + return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText(); + } + + public int getLength() { + return 1; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java new file mode 100644 index 0000000000..8ae6926cc6 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java @@ -0,0 +1,30 @@ +package jvm.command.item; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + protected int operand; + + public OneOperandCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + protected void initOperands(CommandIterator iterator) { + setOperand(iterator.next2CharAsInt()); + } + + public int getOperand() { + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + } + + public int getLength() { + return 2; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/TwoOperandCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/TwoOperandCmd.java new file mode 100644 index 0000000000..53dbd84b39 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/TwoOperandCmd.java @@ -0,0 +1,74 @@ +package jvm.command.item; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.command.CommandIterator; + +public abstract class TwoOperandCmd extends ByteCodeCommand { + + protected int operand1; + protected int operand2; + + public int getOperand1() { + return operand1; + } + + public void setOperand1(int operand1) { + this.operand1 = operand1; + } + + public void setOperand2(int operand2) { + this.operand2 = operand2; + } + + public int getOperand2() { + return operand2; + } + + public TwoOperandCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + protected void initOperands(CommandIterator iterator) { + setOperand1(iterator.next2CharAsInt()); + setOperand2(iterator.next2CharAsInt()); + } + + public int getIndex() { + int operand1 = this.getOperand1(); + int operand2 = this.getOperand2(); + return operand1 << 8 | operand2; + } + + 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(); + Constant 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/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java new file mode 100644 index 0000000000..9673b3f441 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ALoad0Cmd extends NoOperandCmd { + public ALoad0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java new file mode 100644 index 0000000000..549602b291 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ALoad1Cmd extends NoOperandCmd { + public ALoad1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java new file mode 100644 index 0000000000..12dc0c6088 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ALoad2Cmd extends NoOperandCmd { + public ALoad2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java new file mode 100644 index 0000000000..2c151b2de2 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ALoad3Cmd extends NoOperandCmd { + public ALoad3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java new file mode 100644 index 0000000000..71909a5a22 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class AStore0Cmd extends NoOperandCmd { + public AStore0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java new file mode 100644 index 0000000000..379da9077c --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class AStore1Cmd extends NoOperandCmd { + public AStore1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java new file mode 100644 index 0000000000..b11cf64bac --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class AStore2Cmd extends NoOperandCmd { + public AStore2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java new file mode 100644 index 0000000000..eedd211522 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class AStore3Cmd extends NoOperandCmd { + public AStore3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java new file mode 100644 index 0000000000..da2b176cb4 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java @@ -0,0 +1,17 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.OneOperandCmd; + +public class BiPushCmd extends OneOperandCmd { + public BiPushCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset() + ": " + this.getOpCode() + " " + this.getReadableCodeText() + " " + this.getOperand(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java new file mode 100644 index 0000000000..d9d02922fb --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class DupCmd extends NoOperandCmd { + public DupCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java new file mode 100644 index 0000000000..e0e4701bc3 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } + + +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java new file mode 100644 index 0000000000..16959b04e0 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java @@ -0,0 +1,19 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class GetStaticCmd extends TwoOperandCmd { + + public GetStaticCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } + +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java new file mode 100644 index 0000000000..c02449abb8 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ILoad0Cmd extends NoOperandCmd { + public ILoad0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java new file mode 100644 index 0000000000..ee35698dce --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ILoad1Cmd extends NoOperandCmd { + public ILoad1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java new file mode 100644 index 0000000000..1f0962b1a8 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ILoad2Cmd extends NoOperandCmd { + public ILoad2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java new file mode 100644 index 0000000000..dd64684d1a --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ILoad3Cmd extends NoOperandCmd { + public ILoad3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java new file mode 100644 index 0000000000..3bc0281582 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java @@ -0,0 +1,17 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class InvokeSpecialCmd extends TwoOperandCmd { + public InvokeSpecialCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsMethod(pool); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c5809c1ea8 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java @@ -0,0 +1,17 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class InvokeVirtualCmd extends TwoOperandCmd { + public InvokeVirtualCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsMethod(pool); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java new file mode 100644 index 0000000000..73e7aa8f8e --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java @@ -0,0 +1,27 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.StringInfo; +import jvm.command.CommandIterator; +import jvm.command.item.OneOperandCmd; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + Constant info = 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/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java new file mode 100644 index 0000000000..67a598a624 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java @@ -0,0 +1,19 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class NewCmd extends TwoOperandCmd { + + public NewCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java new file mode 100644 index 0000000000..58628d8dff --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java @@ -0,0 +1,18 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java new file mode 100644 index 0000000000..cc46fe4caa --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java @@ -0,0 +1,20 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class ReturnCmd extends NoOperandCmd { + public ReturnCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } +} From d50051f74762dcca8f264996bda300972bf47f7c Mon Sep 17 00:00:00 2001 From: Haochen Date: Thu, 20 Apr 2017 17:24:40 +0800 Subject: [PATCH 078/151] finish byte code command parsing --- .../main/java/jvm/classfile/ClassFile.java | 19 +++- .../main/java/jvm/classfile/ClassParser.java | 2 +- .../attribute/item/AttributeInfo.java | 2 +- .../attribute/item/impl/CodeAttr.java | 2 +- .../java/jvm/classfile/method/Method.java | 30 ++++- .../src/main/java/jvm/util/ByteUtils.java | 4 +- .../test/java/jvm/ClassFileLoaderTest.java | 107 ++++++++++++++---- 7 files changed, 133 insertions(+), 33 deletions(-) diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java index 41f983a086..377b198035 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java @@ -1,6 +1,5 @@ package jvm.classfile; - import jvm.classfile.attribute.item.AttributeInfo; import jvm.classfile.constant.item.impl.ClassInfo; import jvm.classfile.field.Field; @@ -24,6 +23,10 @@ public class ClassFile { List methods = new ArrayList<>(); List attributes = new ArrayList<>(); + + public AccessFlag getAccessFlag() { + return accessFlag; + } public List getInterfaces() { return this.interfaces; } @@ -45,13 +48,13 @@ public void print() { System.out.println("Super Class Name:"+ getSuperClassName()); } - private String getClassName() { + public String getClassName() { int thisClassIndex = this.classIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } - private String getSuperClassName() { + public String getSuperClassName() { ClassInfo superClass = (ClassInfo)this.getConstantPool() .getConstantInfo(this.classIndex.getSuperClassIndex()); return superClass.getClassName(); @@ -72,4 +75,14 @@ public ConstantPool getConstantPool() { public ClassIndex getClzIndex() { return classIndex; } + + public Method getMethod(String methodName, String paramAndReturnType) { + return methods.stream().filter(m -> methodName.equals(m.getName()) + && paramAndReturnType.equals(m.getParamAndReturnType())) + .findFirst().orElse(null); + } + + public Method getMainMethod() { + return getMethod("main", "([Ljava/lang/String;)V"); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java index fa3a07527d..bec7317e2c 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java @@ -98,7 +98,7 @@ private static void parseFields(ClassFile classFile, ByteCodeIterator iterator) private static void parseMethods(ClassFile classFile, ByteCodeIterator iterator) { int count = iterator.nextU2ToInt(); for (int i = 0; i < count; ++i) { - classFile.methods.add(Method.parse(iterator, classFile.constantPool)); + classFile.methods.add(Method.parse(iterator, classFile)); } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java index 595c12ac9b..7afcc1f786 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java @@ -8,7 +8,7 @@ public abstract class AttributeInfo { public static final String LOCAL_VAR_TABLE = "LocalVariableTable"; public static final String STACK_MAP_TABLE = "StackMapTable"; - int attrNameIndex; + int attrNameIndex; int attrLen; public AttributeInfo(int attrNameIndex, int attrLen) { diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java index 75c7383bd8..5ae1a8267a 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java @@ -13,7 +13,7 @@ public class CodeAttr extends AttributeInfo { private List attributes = new ArrayList<>(); //private ByteCodeCommand[] cmds ; - //public ByteCodeCommand[] getCmds() { + //public ByteCodeCommand[] getCommands() { // return cmds; //} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java b/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java index 6068124fa3..916a4aa32b 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java @@ -1,20 +1,25 @@ package jvm.classfile.method; +import jvm.classfile.ClassFile; import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.CodeAttr; import jvm.classfile.attribute.parser.AttributeParser; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.UTF8Info; +import jvm.command.CommandParser; +import jvm.command.item.ByteCodeCommand; import jvm.util.ByteCodeIterator; import java.util.ArrayList; import java.util.List; - public class Method { private int accessFlag; private int nameIndex; private int descriptorIndex; private ConstantPool constantPool; private List attributes = new ArrayList<>(); + private ByteCodeCommand[] commands; public Method(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { this.accessFlag = accessFlag; @@ -23,14 +28,19 @@ public Method(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool c this.constantPool = constantPool; } - public static Method parse(ByteCodeIterator iterator, ConstantPool constantPool) { + public static Method parse(ByteCodeIterator iterator, ClassFile classFile) { int access = iterator.nextU2ToInt(); int name = iterator.nextU2ToInt(); int descriptor = iterator.nextU2ToInt(); int attrCount = iterator.nextU2ToInt(); - Method result = new Method(access, name, descriptor, constantPool); + Method result = new Method(access, name, descriptor, classFile.getConstantPool()); for (int i = 0; i < attrCount; ++i) { - result.attributes.add(AttributeParser.parse(iterator, constantPool)); + result.attributes.add(AttributeParser.parse(iterator, classFile.getConstantPool())); + } + CodeAttr codeAttr = (CodeAttr) result.attributes.stream() + .filter(a -> a instanceof CodeAttr).findFirst().orElse(null); + if (codeAttr != null) { + result.commands = CommandParser.parse(classFile, codeAttr.getCode()); } return result; } @@ -54,4 +64,16 @@ public List getAttributes() { public int getDescriptorIndex() { return descriptorIndex; } + + public ByteCodeCommand[] getCommands() { + return commands; + } + + public String getName() { + return ((UTF8Info) getConstantPool().getConstantInfo(getNameIndex())).getValue(); + } + + public String getParamAndReturnType() { + return ((UTF8Info) getConstantPool().getConstantInfo(getDescriptorIndex())).getValue(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java index 3a0e1fc0b6..87afccab3c 100644 --- a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java +++ b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java @@ -8,7 +8,9 @@ public class ByteUtils { public static String toHexString(byte[] bytes, int off, int len) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < len; ++i) { - builder.append(Integer.toHexString(Byte.toUnsignedInt(bytes[off + i]))); + int uInt = Byte.toUnsignedInt(bytes[off + i]); + String hex = Integer.toHexString(uInt); + builder.append(hex.length() < 2 ? '0' + hex : hex); } return builder.toString(); } diff --git a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java index 23a2341d8f..daaa65a680 100644 --- a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java +++ b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java @@ -8,6 +8,10 @@ import jvm.classfile.constant.item.impl.MethodRefInfo; import jvm.classfile.constant.item.impl.NameAndTypeInfo; import jvm.classfile.constant.item.impl.UTF8Info; +import jvm.command.item.impl.BiPushCmd; +import jvm.command.item.ByteCodeCommand; +import jvm.command.item.OneOperandCmd; +import jvm.command.item.TwoOperandCmd; import jvm.exception.ReadClassException; import jvm.classfile.field.Field; import jvm.classfile.method.Method; @@ -64,23 +68,6 @@ public void testMagicNumber() throws ReadClassException { Assert.assertTrue(check); } - private String byteToHexString(byte[] codes) { - StringBuilder buffer = new StringBuilder(); - for (byte b : codes) { - int value = b & 0xFF; - String strHex = Integer.toHexString(value); - if (strHex.length() < 2) { - strHex = "0" + strHex; - } - buffer.append(strHex); - } - return buffer.toString(); - } - - - - - @Test public void testVersion() { Assert.assertEquals(0, clzFile.getMinorVersion()); @@ -194,7 +181,7 @@ public void testMethods() { assertMethodEquals(pool,m, "", "(Ljava/lang/String;I)V", - "2ab7012a2bb5022a1cb503b1"); + "2ab700012a2bb500022a1cb50003b1"); } { @@ -202,7 +189,7 @@ public void testMethods() { assertMethodEquals(pool,m, "setName", "(Ljava/lang/String;)V", - "2a2bb502b1"); + "2a2bb50002b1"); } { @@ -210,14 +197,14 @@ public void testMethods() { assertMethodEquals(pool,m, "setAge", "(I)V", - "2a1bb503b1"); + "2a1bb50003b1"); } { Method m = methods.get(3); assertMethodEquals(pool,m, "sayHello", "()V", - "b204125b606b1"); + "b200041205b60006b1"); } { @@ -225,7 +212,7 @@ public void testMethods() { assertMethodEquals(pool,m, "main", "([Ljava/lang/String;)V", - "bb0759128101db7094c2bb60ab1"); + "bb0007591208101db700094c2bb6000ab1"); } } @@ -238,4 +225,80 @@ private void assertMethodEquals(ConstantPool pool, Method m, Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } + @Test + public void testByteCodeCommand(){ + { + Method initMethod = clzFile.getMethod("", + "(Ljava/lang/String;I)V"); + ByteCodeCommand [] cmds = initMethod.getCommands(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: invokespecial #1", cmds[1]); + assertOpCodeEquals("4: aload_0", cmds[2]); + assertOpCodeEquals("5: aload_1", cmds[3]); + assertOpCodeEquals("6: putfield #2", cmds[4]); + assertOpCodeEquals("9: aload_0", cmds[5]); + assertOpCodeEquals("10: iload_2", cmds[6]); + assertOpCodeEquals("11: putfield #3", cmds[7]); + assertOpCodeEquals("14: return", cmds[8]); + } + + { + Method setNameMethod = clzFile.getMethod("setName", + "(Ljava/lang/String;)V"); + ByteCodeCommand [] cmds = setNameMethod.getCommands(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: aload_1", cmds[1]); + assertOpCodeEquals("2: putfield #2", cmds[2]); + assertOpCodeEquals("5: return", cmds[3]); + + } + + { + Method sayHelloMethod = clzFile.getMethod("sayHello", + "()V"); + ByteCodeCommand [] cmds = sayHelloMethod.getCommands(); + + assertOpCodeEquals("0: getstatic #4", cmds[0]); + assertOpCodeEquals("3: ldc #5", cmds[1]); + assertOpCodeEquals("5: invokevirtual #6", cmds[2]); + assertOpCodeEquals("8: return", cmds[3]); + + } + + { + Method mainMethod = clzFile.getMainMethod(); + + ByteCodeCommand [] cmds = mainMethod.getCommands(); + + assertOpCodeEquals("0: new #7", cmds[0]); + assertOpCodeEquals("3: dup", cmds[1]); + assertOpCodeEquals("4: ldc #8", cmds[2]); + assertOpCodeEquals("6: bipush 29", cmds[3]); + assertOpCodeEquals("8: invokespecial #9", cmds[4]); + assertOpCodeEquals("11: astore_1", cmds[5]); + assertOpCodeEquals("12: aload_1", cmds[6]); + assertOpCodeEquals("13: invokevirtual #10", 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 80fa24053da37743b5a9f0543793bce639952588 Mon Sep 17 00:00:00 2001 From: zheng <765324639@qq.com> Date: Thu, 20 Apr 2017 20:18:21 +0800 Subject: [PATCH 079/151] =?UTF-8?q?jvm=E7=AC=AC=E5=9B=9B=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=EF=BC=88=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E9=83=A8=E5=88=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stack/expr/InfixToPostfix.java | 52 ++++++++++++++++++ .../datastructure/stack/expr/PostfixExpr.java | 53 ++++++++++++++++++ .../datastructure/stack/expr/PrefixExpr.java | 55 +++++++++++++++++++ .../java/datastructure/stack/expr/Token.java | 22 +++++++- .../datastructure/stack/expr/TokenParser.java | 4 +- .../stack/expr/InfixExprTest.java | 5 +- .../stack/expr/InfixToPostfixTest.java | 53 ++++++++++++++++++ .../stack/expr/PostfixExprTest.java | 38 +++++++++++++ .../stack/expr/PrefixExprTest.java | 44 +++++++++++++++ 9 files changed, 322 insertions(+), 4 deletions(-) create mode 100644 group01/765324639/src/main/java/datastructure/stack/expr/InfixToPostfix.java create mode 100644 group01/765324639/src/main/java/datastructure/stack/expr/PostfixExpr.java create mode 100644 group01/765324639/src/main/java/datastructure/stack/expr/PrefixExpr.java create mode 100644 group01/765324639/src/test/java/datastructure/stack/expr/InfixToPostfixTest.java create mode 100644 group01/765324639/src/test/java/datastructure/stack/expr/PostfixExprTest.java create mode 100644 group01/765324639/src/test/java/datastructure/stack/expr/PrefixExprTest.java diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/InfixToPostfix.java b/group01/765324639/src/main/java/datastructure/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..18fdf3b391 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/InfixToPostfix.java @@ -0,0 +1,52 @@ +package datastructure.stack.expr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + + TokenParser tokenParser = new TokenParser(expr); + List tokenList = tokenParser.parse(); + + Stack operStack = new Stack<>(); + Stack tempStack = new Stack<>(); + for (int i = 0; i < tokenList.size(); i++) { + Token token = tokenList.get(i); + if (token.isNumber()) { + tempStack.push(token); + } else if (token.isOperator()) { + if (operStack.isEmpty() || "(".equals(operStack.peek().getValue())) { + operStack.push(token); + } else if (")".equals(token.getValue())) { + while (!"(".equals(operStack.peek().getValue())) { + tempStack.push(operStack.pop()); + } + operStack.pop(); // 去掉左括号 + } else if (token.comparePriority(operStack.peek()) > 0){ + operStack.push(token); + } else { + tempStack.push(operStack.pop()); + i--; + } + } + } + + while (!operStack.empty()) { + tempStack.push(operStack.pop()); + } + + List list = new ArrayList<>(); + while (!tempStack.empty()) { + list.add(tempStack.pop()); + } + Collections.reverse(list); + return list; + } + + + +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/PostfixExpr.java b/group01/765324639/src/main/java/datastructure/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..98a0156df0 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/PostfixExpr.java @@ -0,0 +1,53 @@ +package datastructure.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() { + TokenParser tokenParser = new TokenParser(expr); + List tokenList = tokenParser.parse(); + + Stack floatStack = new Stack<>(); + + for (Token token : tokenList) { + if (token.isNumber()) { + floatStack.push(Float.valueOf(token.getValue())); + } else if (token.isOperator()) { + float num2 = floatStack.pop(); + float num1 = floatStack.pop(); + float result = calculate(token.getValue(), num1, num2); + floatStack.push(result); + } + } + + return floatStack.pop(); + } + + private float calculate(String operator, float num1, float num2) { + float result = 0; + switch (operator.charAt(0)) { + case '+': + result = num1 + num2; + break; + case '-': + result = num1 - num2; + break; + case '*': + result = num1 * num2; + break; + case '/': + result = num1 / num2; + break; + default: + throw new IllegalArgumentException(); + } + return result; + } +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/PrefixExpr.java b/group01/765324639/src/main/java/datastructure/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..ebec17a78c --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/PrefixExpr.java @@ -0,0 +1,55 @@ +package datastructure.stack.expr; + +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(expr); + List tokenList = tokenParser.parse(); + Collections.reverse(tokenList); + + Stack floatStack = new Stack<>(); + + for (Token token : tokenList) { + if (token.isNumber()) { + floatStack.push(Float.valueOf(token.getValue())); + } else if (token.isOperator()) { + float num1 = floatStack.pop(); + float num2 = floatStack.pop(); + float result = calculate(token.getValue(), num1, num2); + floatStack.push(result); + } + } + + return floatStack.pop(); + } + + private float calculate(String operator, float num1, float num2) { + float result = 0; + switch (operator.charAt(0)) { + case '+': + result = num1 + num2; + break; + case '-': + result = num1 - num2; + break; + case '*': + result = num1 * num2; + break; + case '/': + result = num1 / num2; + break; + default: + throw new IllegalArgumentException(); + } + return result; + } +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/Token.java b/group01/765324639/src/main/java/datastructure/stack/expr/Token.java index 44a019197d..e278a5df87 100644 --- a/group01/765324639/src/main/java/datastructure/stack/expr/Token.java +++ b/group01/765324639/src/main/java/datastructure/stack/expr/Token.java @@ -45,7 +45,27 @@ public int comparePriority(Token token) { } return 1; } else { - throw new RuntimeException("不支持的运算符"); + throw new RuntimeException("不支持的运算符:" + token.getValue()); } } + + public boolean isNumber() { + if (NUMBER.equals(type)) { + return true; + } + return false; + } + + public boolean isOperator() { + if (OPERATOR.equals(OPERATOR)) { + return true; + } + return false; + } + + @Override + public String toString() { + return "Token [type=" + type + ", value=" + value + "]"; + } + } diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java b/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java index e1add57663..e3595c8a7a 100644 --- a/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java +++ b/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java @@ -40,8 +40,8 @@ private boolean isNumber(char c) { } private boolean isOperator(char c) { - String supplyOperator = "+-*/"; - if (supplyOperator.indexOf(supplyOperator) != -1) { + String supplyOperator = "+-*/()"; + if (supplyOperator.indexOf(c) != -1) { return true; } return false; diff --git a/group01/765324639/src/test/java/datastructure/stack/expr/InfixExprTest.java b/group01/765324639/src/test/java/datastructure/stack/expr/InfixExprTest.java index 9746dcdb79..ceffd5d7c1 100644 --- a/group01/765324639/src/test/java/datastructure/stack/expr/InfixExprTest.java +++ b/group01/765324639/src/test/java/datastructure/stack/expr/InfixExprTest.java @@ -42,7 +42,10 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } - + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } } } diff --git a/group01/765324639/src/test/java/datastructure/stack/expr/InfixToPostfixTest.java b/group01/765324639/src/test/java/datastructure/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..a5ac1b8f78 --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,53 @@ +package datastructure.stack.expr; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class InfixToPostfixTest { + + @Test + public void testConvert() { + { + String expr = "((2+3)*8+5+3)*6"; + + List postFix = InfixToPostfix.convert(expr); + String postFixExpr = tokenListToString(postFix); + float postFixExprResult = calculatePostFixExpr(postFixExpr); + + Assert.assertEquals(288, postFixExprResult, 0.001); + } + { + String expr = "9+(3-1)*3+10/2"; + + List postFix = InfixToPostfix.convert(expr); + String postFixExpr = tokenListToString(postFix); + float postFixExprResult = calculatePostFixExpr(postFixExpr); + + Assert.assertEquals(20, postFixExprResult, 0.001); + } + { + String expr = "10-2*3+50"; + + List postFix = InfixToPostfix.convert(expr); + String postFixExpr = tokenListToString(postFix); + float postFixExprResult = calculatePostFixExpr(postFixExpr); + + Assert.assertEquals(54, postFixExprResult, 0.001); + } + } + + private String tokenListToString(List tokenList) { + StringBuilder builder = new StringBuilder(); + for (Token token : tokenList) { + builder.append(token.getValue() + " "); + } + return builder.toString(); + } + + private float calculatePostFixExpr(String expr) { + PostfixExpr postfixExpr = new PostfixExpr(expr); + return postfixExpr.evaluate(); + } +} diff --git a/group01/765324639/src/test/java/datastructure/stack/expr/PostfixExprTest.java b/group01/765324639/src/test/java/datastructure/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..07036c7577 --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/expr/PostfixExprTest.java @@ -0,0 +1,38 @@ +package datastructure.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() { + { + // ((2+3)*8+5+3)*6 + 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/group01/765324639/src/test/java/datastructure/stack/expr/PrefixExprTest.java b/group01/765324639/src/test/java/datastructure/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..7c7344bfac --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/expr/PrefixExprTest.java @@ -0,0 +1,44 @@ +package datastructure.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); + } + + + } + +} From 43607d3df44b89abf4617a9e64a595318a84818a Mon Sep 17 00:00:00 2001 From: johnChnia Date: Fri, 21 Apr 2017 00:20:58 +0800 Subject: [PATCH 080/151] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B8=AD=E5=BA=8F?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExpr.java | 6 ++- .../basic/stack/expr/InfixToPostfix.java | 39 +++++++++++++++---- .../coding2017/basic/stack/expr/Operator.java | 5 ++- .../basic/stack/expr/PostfixExpr.java | 13 ++++++- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java index ddafe58c46..d3e9afbf9b 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExpr.java @@ -1,5 +1,8 @@ package com.johnChnia.coding2017.basic.stack.expr; + +import com.johnChnia.coding2017.basic.List; + public class InfixExpr { String expr = null; @@ -8,7 +11,8 @@ public InfixExpr(String expr) { } public float evaluate() { - return 0.0f; + List tokens = InfixToPostfix.convert(this.expr); + return PostfixExpr.evaluate(tokens); } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java index f42f73282a..e361815f02 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java @@ -1,14 +1,37 @@ package com.johnChnia.coding2017.basic.stack.expr; -import java.util.List; +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.List; +import com.johnChnia.coding2017.basic.stack.Stack; + + +/*** + * Rule: + */ public class InfixToPostfix { - - public static List convert(String expr) { - - return null; - } - - + + public static List convert(String expr) { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + List list = new ArrayList<>(); + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + Token token = tokens.get(i); + if (token.isNumber()) { + list.add(token); + } else if (token.isOperator()) { + while (!stack.empty() && !token.hasHigherPriority(stack.peek())) { + list.add(stack.pop()); + } + stack.push(token); + + } + } + while (!stack.empty()) { + list.add(stack.pop()); + } + return list; + } } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java index 52ff15fa80..adc1aac489 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Operator.java @@ -17,6 +17,7 @@ public void handlerToken(String fix, Stack stack, Token token) { } } + private float perform(String fix, String operator, float p, float q) { float result = 0.0f; if (operator.equals("+")) { @@ -24,7 +25,7 @@ private float perform(String fix, String operator, float p, float q) { } else if (operator.equals("-")) { if (fix.equals("postfix")) { result = q - p; - } else if (fix.equals("prefix")){ + } else if (fix.equals("prefix")) { result = p - q; } } else if (operator.equals("*")) { @@ -32,7 +33,7 @@ private float perform(String fix, String operator, float p, float q) { } else if (operator.equals("/")) { if (fix.equals("postfix")) { result = q / p; - } else if (fix.equals("prefix")){ + } else if (fix.equals("prefix")) { result = p / q; } } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java index dfecd16ed4..4046c13830 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/PostfixExpr.java @@ -4,7 +4,9 @@ import com.johnChnia.coding2017.basic.stack.Stack; public class PostfixExpr { - String expr = null; + private String expr = null; + static Operator operator = new Operator(); + public PostfixExpr(String expr) { this.expr = expr; @@ -13,7 +15,6 @@ public PostfixExpr(String expr) { public float evaluate() { TokenParser tokenParser = new TokenParser(); List tokens = tokenParser.parse(this.expr); - Operator operator = new Operator(); Stack stack = new Stack<>(); for (int i = 0; i < tokens.size(); i++) { operator.handlerToken("postfix", stack, tokens.get(i)); @@ -23,5 +24,13 @@ public float evaluate() { return stack.pop(); } + public static float evaluate(List tokens) { + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + operator.handlerToken("postfix", stack, tokens.get(i)); + } + return stack.pop(); + } + } From bf84de24d57c4a3857bc508d8a243049db555084 Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 21 Apr 2017 00:23:51 +0800 Subject: [PATCH 081/151] =?UTF-8?q?jvm=20=E5=AD=97=E8=8A=82=E7=A0=81?= =?UTF-8?q?=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/minijvm/attr/CodeAttr.java | 8 ++- .../coding2017/minijvm/clz/ClassFile.java | 15 +++-- .../coding2017/minijvm/cmd/CommandParser.java | 65 ++++++++++++++++++- .../coding2017/minijvm/method/Method.java | 13 ++++ 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java index ff7fcc4294..c4455c6b2a 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/CodeAttr.java @@ -2,6 +2,7 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.cmd.ByteCodeCommand; +import com.github.ipk2015.coding2017.minijvm.cmd.CommandParser; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator; @@ -22,7 +23,7 @@ public ByteCodeCommand[] getCmds() { 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; @@ -46,7 +47,10 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int maxLocals = iter.nextUNToInt(2); int codeLen = iter.nextUNToInt(4); String code = iter.nextUNToHexString(codeLen); - CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code); + + ByteCodeCommand[] commands = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code,commands); int exceptionTableLen = iter.nextUNToInt(2); if(exceptionTableLen != 0){ throw new RuntimeException("code属性里的异常table长度为:"+exceptionTableLen); diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java index 5c3706b76f..3a267144af 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java @@ -5,6 +5,7 @@ import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.UTF8Info; import com.github.ipk2015.coding2017.minijvm.field.Field; import com.github.ipk2015.coding2017.minijvm.method.Method; @@ -90,12 +91,18 @@ public String getSuperClassName(){ return superClass.getClassName(); } public Method getMethod(String methodName, String paramAndReturnType){ - - + List list = getMethods(); + for(Method m : list){ + String name = ((UTF8Info)pool.getConstantInfo(m.getNameIndex())).getValue(); + String desc = ((UTF8Info)pool.getConstantInfo(m.getDescriptorIndex())).getValue(); + if(name.equalsIgnoreCase(methodName) && desc.equalsIgnoreCase(paramAndReturnType)){ + return m; + } + } return null; } public Method getMainMethod(){ - - return null; +// main:([Ljava/lang/String;)V + return getMethod("main","([Ljava/lang/String;)V"); } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java index 23b2859e6a..d9c3c619e2 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/CommandParser.java @@ -1,5 +1,6 @@ package com.github.ipk2015.coding2017.minijvm.cmd; +import java.util.ArrayList; import java.util.List; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; @@ -42,9 +43,67 @@ public class CommandParser { public static final String iinc = "84"; public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { - - - return null; + if(null == codes || codes.length() == 0){ + throw new RuntimeException("字节码不存在"); + } + codes = codes.toUpperCase(); + CommandIterator iterator = new CommandIterator(codes); + List commands = new ArrayList(); + while(iterator.hasNext()){ + String operatorCode = iterator.next2CharAsString(); + if(ldc.equals(operatorCode)){ + LdcCmd cmd = new LdcCmd(clzFile,operatorCode); + cmd.setOperand(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(bipush.equals(operatorCode)){ + BiPushCmd cmd = new BiPushCmd(clzFile,operatorCode); + cmd.setOperand(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(new_object.equals(operatorCode)){ + NewObjectCmd cmd = new NewObjectCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(invokespecial.equals(operatorCode)){ + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(invokevirtual.equals(operatorCode)){ + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(putfield.equals(operatorCode)){ + PutFieldCmd cmd = new PutFieldCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(getfield.equals(operatorCode)){ + GetFieldCmd cmd = new GetFieldCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(getstatic.equals(operatorCode)){ + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile,operatorCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(dup.equals(operatorCode) || aload_0.equals(operatorCode) || aload_1.equals(operatorCode) || + aload_2.equals(operatorCode) || astore_1.equals(operatorCode) || voidreturn.equals(operatorCode) + || iload.equals(operatorCode) || iload_1.equals(operatorCode) || iload_2.equals(operatorCode) + || iload_3.equals(operatorCode) || fload_3.equals(operatorCode) || iconst_0.equals(operatorCode) + || iconst_1.equals(operatorCode) || istore_1.equals(operatorCode) || istore_2.equals(operatorCode) + || iadd.equals(operatorCode)|| iinc.equals(operatorCode)){ + NoOperandCmd command = new NoOperandCmd(clzFile,operatorCode); + commands.add(command); + }else{ + throw new RuntimeException("this operator code not includes yet:"+operatorCode); + } + } + calcuateOffset(commands); + ByteCodeCommand[] result = new ByteCodeCommand[commands.size()]; + return commands.toArray(result); } private static void calcuateOffset(List cmds) { diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java index 61b91fa7b9..b8a3d7dca2 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java @@ -4,6 +4,8 @@ import com.github.ipk2015.coding2017.minijvm.attr.CodeAttr; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.cmd.ByteCodeCommand; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.UTF8Info; import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator; public class Method { @@ -71,4 +73,15 @@ private static void addAttr(ClassFile clzFile,Method method,ByteCodeIterator ite public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + 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(); + } } From 8bdf0c67b02fa4e452d317a5763251690b16a189 Mon Sep 17 00:00:00 2001 From: "kaitao.li" Date: Fri, 21 Apr 2017 09:17:49 +0800 Subject: [PATCH 082/151] =?UTF-8?q?jvm=E7=AC=AC=E4=B8=89=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A,=20=E6=96=B9=E6=B3=95=E8=A7=A3=E6=9E=90done?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/coding2017/jvm/attr/CodeAttr.java | 6 ++++++ .../coding2017/jvm/attr/LineNumberTable.java | 16 ++++++++++++---- .../jvm/attr/LocalVariableTable.java | 14 ++++++++++++-- .../com/coding2017/jvm/attr/StackMapTable.java | 7 ++----- .../java/com/coding2017/jvm/field/Field.java | 4 ++++ .../coding2017/jvm/loader/ClassFileParser.java | 18 ++++++++++++++++-- .../java/com/coding2017/jvm/method/Method.java | 4 +++- .../jvm/loader/ClassFileLoaderTest.java | 2 +- 8 files changed, 56 insertions(+), 15 deletions(-) diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java index 93bebc2dc7..b248bdc490 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/CodeAttr.java @@ -45,6 +45,12 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter, int nameI int codeLength = iter.nextU4ToInt(); String code = iter.nextUxToHexString(codeLength); CodeAttr codeAttr = new CodeAttr(nameIndex, length, maxStack, maxLocals, codeLength, code); + int exceptionTableLength = iter.nextU2ToInt(); + if(exceptionTableLength > 0){ + String exTable = iter.nextUxToHexString(exceptionTableLength * 8); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } int codeAttributeCount = iter.nextU2ToInt(); for (int j = 0; j < codeAttributeCount; j++) { AttributeInfo attributeInfo = AttributeInfo.parse(clzFile, iter); diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java index 2878f874ed..68d21f9244 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LineNumberTable.java @@ -1,11 +1,11 @@ package com.coding2017.jvm.attr; -import com.coding2017.jvm.clz.ClassFile; -import com.coding2017.jvm.loader.ByteCodeIterator; - import java.util.ArrayList; import java.util.List; +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.jvm.loader.ByteCodeIterator; + public class LineNumberTable extends AttributeInfo { List items = new ArrayList(); @@ -40,8 +40,16 @@ public LineNumberTable(int attrNameIndex, int attrLen) { } public static LineNumberTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { + int tableLength = iter.nextU2ToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(nameIndex, length); + for (int i = 0; i < tableLength; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLineNum(iter.nextU2ToInt()); + lineNumberTable.addLineNumberItem(item); + } - return null; + return lineNumberTable; } } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java index 23dff851c8..fb039b6f16 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/LocalVariableTable.java @@ -15,8 +15,18 @@ public LocalVariableTable(int attrNameIndex, int attrLen) { } public static LocalVariableTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { - - return null; + int tableLength = iter.nextU2ToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(nameIndex, length); + for (int i = 0; i < tableLength; 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()); + localVariableTable.addLocalVariableItem(item); + } + return localVariableTable; } private void addLocalVariableItem(LocalVariableItem item) { diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java index 653ecab830..12e6d80c5c 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/attr/StackMapTable.java @@ -12,12 +12,10 @@ public StackMapTable(int attrNameIndex, int attrLen) { } public static StackMapTable parse(ClassFile clzFile, ByteCodeIterator iter, int nameIndex, int length) { - int index = iter.nextU2ToInt(); - int len = iter.nextU4ToInt(); - StackMapTable t = new StackMapTable(index, len); + StackMapTable t = new StackMapTable(nameIndex, length); // 后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 - String code = iter.nextUxToHexString(len); + String code = iter.nextUxToHexString(length); t.setOriginalCode(code); return t; @@ -25,6 +23,5 @@ public static StackMapTable parse(ClassFile clzFile, ByteCodeIterator iter, int private void setOriginalCode(String code) { this.originalCode = code; - } } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java index d521fca4e3..10e1bbb870 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/field/Field.java @@ -29,4 +29,8 @@ public static Field parse(ConstantPool pool, ByteCodeIterator iter) { return new Field(accessFlag, nameIndex, descriptorIndex, pool); } + @Override + public String toString() { + return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex); + } } diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java index 87cf762ac4..b1d11f634d 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java @@ -34,13 +34,27 @@ public ClassFile parse(byte[] codes) { parseInterfaces(iterator); - Field.parse(classFile.getConstantPool(), iterator); + parseFields(classFile, iterator); - Method.parse(classFile, iterator); + parseMethods(classFile, iterator); return classFile; } + private void parseMethods(ClassFile clzFile, ByteCodeIterator iterator) { + int methodCount = iterator.nextU2ToInt(); + for (int i = 0; i < methodCount; i++) { + clzFile.getMethods().add(Method.parse(clzFile, iterator)); + } + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iterator) { + int fieldCount = iterator.nextU2ToInt(); + for (int i = 0; i < fieldCount; i++) { + clzFile.getFields().add(Field.parse(clzFile.getConstantPool(), iterator)); + } + } + private boolean checkMagicNumber(ByteCodeIterator iterator) { String magicNumber = iterator.nextU4ToString(); return "cafebabe".equals(magicNumber); diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java index 90ad8dec1e..173e966a7f 100644 --- a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/method/Method.java @@ -49,7 +49,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); method.parseAttributes(iter); - return null; + return method; } @@ -59,6 +59,8 @@ private void parseAttributes(ByteCodeIterator iter) { AttributeInfo attributeInfo = AttributeInfo.parse(this.clzFile, iter); if (attributeInfo instanceof CodeAttr) { this.setCodeAttr((CodeAttr) attributeInfo); + } else { + throw new RuntimeException("unknown method attribute"); } } } diff --git a/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java index d9dd2a22ff..0b87979626 100644 --- a/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java +++ b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java @@ -74,7 +74,7 @@ public void testClassFileLength() { public void testMagicNumber() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coding2017.week4.jvm.test.EmployeeV1"; + String className = "com.coding2017.jvm.bean.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); byte[] codes = new byte[] { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; From aaf64e80887e3e642193ab34cdacf2a01f2f4ce3 Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Fri, 21 Apr 2017 10:24:47 +0800 Subject: [PATCH 083/151] =?UTF-8?q?=E5=89=8D=E5=BA=8F=E5=90=8E=E5=BA=8F?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E8=A1=A8=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding/basic/stack/expr/PostfixExpr.java | 41 ++++++++++++++++++- .../coding/basic/stack/expr/PrefixExpr.java | 34 ++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java index db7e5a4c6a..2040814b2c 100644 --- a/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PostfixExpr.java @@ -1,5 +1,9 @@ package com.coding.basic.stack.expr; +import java.util.List; +import java.util.Stack; + + public class PostfixExpr { String expr = null; @@ -8,11 +12,44 @@ public PostfixExpr(String expr) { } public float evaluate() { + Stack stack = new Stack(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + for(Token token :tokens){ + if(token.isNumber()){ + stack.push(token.toString()); + } + if(token.isOperator()){ + int num1 = Integer.parseInt(stack.pop()); + int num2 = Integer.parseInt(stack.pop()); + String result = parseToResult(num1,num2,token.toString()); + stack.push(result); + } + } - return 0.0f; + return Float.parseFloat(stack.pop()); } - + private String parseToResult(int num1, int num2, String oper) { + // TODO Auto-generated method stub + String result = ""; + if(oper.equals("*")) + result = (num1*num2)+""; + if(oper.equals("/")) + result = (num2/num1)+""; + if(oper.equals("+")) + result = (num1+num2)+""; + if(oper.equals("-")) + result = (num2-num1)+""; + return result; + } + + public static void main(String[] args) { + //9+(3-1)*3+10/2 + PostfixExpr pos = new PostfixExpr("9 3 1-3*+ 10 2/+"); + float f =pos.evaluate(); + System.out.println(f); + } } diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java index f3b4953b51..c06a960bfe 100644 --- a/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/PrefixExpr.java @@ -1,4 +1,6 @@ package com.coding.basic.stack.expr; + +import java.util.Collections; import java.util.List; import java.util.Stack; @@ -10,8 +12,38 @@ public PrefixExpr(String expr) { } public float evaluate() { - return 0.0f; + Stack stack = new Stack(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Collections.reverse(tokens); + for(Token token :tokens){ + if(token.isNumber()){ + stack.push(token.toString()); + } + if(token.isOperator()){ + int num1 = Integer.parseInt(stack.pop()); + int num2 = Integer.parseInt(stack.pop()); + String result = parseToResult(num1,num2,token.toString()); + stack.push(result); + } + } + + return Float.parseFloat(stack.pop()); } + private String parseToResult(int num1, int num2, String oper) { + // TODO Auto-generated method stub + String result = ""; + if(oper.equals("*")) + result = (num1*num2)+""; + if(oper.equals("/")) + result = (num1/num2)+""; + if(oper.equals("+")) + result = (num1+num2)+""; + if(oper.equals("-")) + result = (num1-num2)+""; + return result; + } + } \ No newline at end of file From 133fbe6233473f6477b4f99b82feb29096eb3268 Mon Sep 17 00:00:00 2001 From: zhanglei <383117348@qq.com> Date: Fri, 21 Apr 2017 15:13:53 +0800 Subject: [PATCH 084/151] =?UTF-8?q?=E4=B8=AD=E5=BA=8F=E8=BD=AC=E5=90=8E?= =?UTF-8?q?=E5=BA=8F,=E4=B8=AD=E5=BA=8F=E8=BD=AC=E5=89=8D=E5=BA=8F?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixToPostfix.java | 51 ++++++++++++++++-- .../basic/stack/expr/InfixToPrevfix.java | 54 +++++++++++++++++++ 2 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPrevfix.java diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java index dcee6ecadf..2e7243ecb2 100644 --- a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPostfix.java @@ -1,14 +1,59 @@ package com.coding.basic.stack.expr; +import java.util.ArrayList; import java.util.List; +import org.junit.Assert; + +import com.coding.basic.stack.Stack; + + public class InfixToPostfix { - + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + List result = getPostOrder(tokens); - return null; + return result; } + + /** + * 中序表达式转后序表达式 + * + * @param list + * @return + */ + private static List getPostOrder(List tokens) { + + List result = new ArrayList(); + Stack stack = new Stack(); + for (int i = 0; i < tokens.size(); i++) { + // 如果为数字,加到集合里 + if (tokens.get(i).isNumber()) { + result.add(tokens.get(i)); + } else { + Token token = null; + if(!stack.isEmpty()){ + token = (Token)stack.peek(); + } + while(!stack.isEmpty() && token.hasHigherPriority(tokens.get(i))){ + result.add((Token)stack.pop()); + } + stack.push(tokens.get(i)); + } + } + while (!stack.isEmpty()) { + // 最后看下操作符栈还有操作符没,有了加到集合末尾 + result.add((Token) stack.pop()); + } + return result; + } - + + public static void main(String[] args) { + List list = InfixToPostfix.convert("300*20+12*5-20/4"); + Assert.assertEquals("[300, 20, *, 12, 5, *, +, 20, 4, /, -]", list.toString()); + } } \ No newline at end of file diff --git a/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPrevfix.java b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPrevfix.java new file mode 100644 index 0000000000..d824284eda --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/expr/InfixToPrevfix.java @@ -0,0 +1,54 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; + +import com.coding.basic.stack.Stack; + +public class InfixToPrevfix { + + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + return PrevOrderExpr(tokens); + } + + public static List PrevOrderExpr(List tokens) { + List result = new ArrayList(); + Stack operator = new Stack(); + Stack num = new Stack(); + for (int i = tokens.size() - 1; i >= 0; i--) { + if (tokens.get(i).isNumber()) { + num.push(tokens.get(i)); + } + if (tokens.get(i).isOperator()) { + Token token = null; + if (!operator.isEmpty()) { + token = (Token) operator.peek(); + } + while (!operator.isEmpty() && token.hasHigherPriority(tokens.get(i))) { + num.push((Token) operator.pop()); + } + operator.push(tokens.get(i)); + } + } + while(!operator.isEmpty()){ + num.push(operator.pop()); + } + while (!num.isEmpty()) { + result.add((Token) num.pop()); + } + + + return result; + } + + + public static void main(String[] args) { + List list = InfixToPrevfix.convert("300*20+12*5-20/4"); + Assert.assertEquals("[+, *, 300, 20, -, *, 12, 5, /, 20, 4]", list.toString()); + } +} From fa6590f5807f1021369a78ad7d03d0972bea8a86 Mon Sep 17 00:00:00 2001 From: gongxun Date: Fri, 21 Apr 2017 19:05:11 +0800 Subject: [PATCH 085/151] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.5/constant/ClassInfo.java | 5 ++ .../785396327/4.5/constant/ConstantInfo.java | 23 ++++++- .../785396327/4.5/constant/FieldRefInfo.java | 5 ++ .../785396327/4.5/constant/MethodRefInfo.java | 63 ++++++++++++++++--- .../4.5/constant/NameAndTypeInfo.java | 5 ++ .../4.5/constant/NullConstantInfo.java | 5 ++ .../785396327/4.5/constant/StringInfo.java | 5 ++ group17/785396327/4.5/constant/UTF8Info.java | 6 ++ 8 files changed, 108 insertions(+), 9 deletions(-) diff --git a/group17/785396327/4.5/constant/ClassInfo.java b/group17/785396327/4.5/constant/ClassInfo.java index 1143ac1faa..4bc1f373df 100644 --- a/group17/785396327/4.5/constant/ClassInfo.java +++ b/group17/785396327/4.5/constant/ClassInfo.java @@ -19,6 +19,11 @@ public int getType() { return type; } + @Override + public void accept(Visitor visitor) { + + } + public String getClassName() { int index = getUtf8Index(); UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); diff --git a/group17/785396327/4.5/constant/ConstantInfo.java b/group17/785396327/4.5/constant/ConstantInfo.java index 8e6eaf72cf..156d96827d 100644 --- a/group17/785396327/4.5/constant/ConstantInfo.java +++ b/group17/785396327/4.5/constant/ConstantInfo.java @@ -13,19 +13,38 @@ public abstract class ConstantInfo { public static final int NAME_AND_TYPE_INFO = 12; protected ConstantPool constantPool; - public ConstantInfo(){ + public ConstantInfo() { } public ConstantInfo(ConstantPool pool) { this.constantPool = pool; } + public abstract int getType(); public ConstantPool getConstantPool() { return constantPool; } - public ConstantInfo getConstantInfo(int index){ + + public ConstantInfo getConstantInfo(int index) { return this.constantPool.getConstantInfo(index); } + + public abstract void accept(Visitor visitor); + + public interface Visitor { + void visitClassInfo(ClassInfo info); + + void visitFieldRef(FieldRefInfo info); + + void visitMethodRef(MethodRefInfo info); + + void visitNameAndType(NameAndTypeInfo info); + + void visitString(StringInfo info); + + void visistUTF8(UTF8Info info); + + } } diff --git a/group17/785396327/4.5/constant/FieldRefInfo.java b/group17/785396327/4.5/constant/FieldRefInfo.java index 1e86db4134..7d813221f5 100644 --- a/group17/785396327/4.5/constant/FieldRefInfo.java +++ b/group17/785396327/4.5/constant/FieldRefInfo.java @@ -15,6 +15,11 @@ public int getType() { return type; } + @Override + public void accept(Visitor visitor) { + + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group17/785396327/4.5/constant/MethodRefInfo.java b/group17/785396327/4.5/constant/MethodRefInfo.java index a3df142200..78b6cf74e7 100644 --- a/group17/785396327/4.5/constant/MethodRefInfo.java +++ b/group17/785396327/4.5/constant/MethodRefInfo.java @@ -3,7 +3,7 @@ /** * Created by IBM on 2017/4/10. */ -public class MethodRefInfo extends ConstantInfo { +public class MethodRefInfo extends ConstantInfo implements ConstantInfo.Visitor { private int type = ConstantInfo.METHOD_INFO; private int classInfoIndex; @@ -17,32 +17,81 @@ public int getType() { return type; } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } + public void setClassInfoIndex(int classInfoIndex) { this.classInfoIndex = classInfoIndex; } + public int getNameAndTypeIndex() { return nameAndTypeIndex; } + public void setNameAndTypeIndex(int nameAndTypeIndex) { this.nameAndTypeIndex = nameAndTypeIndex; } - public String toString(){ + public String toString() { - return getClassName() +" : "+ this.getMethodName() + " : " + this.getNameAndTypeIndex() ; + return getClassName() + " : " + this.getMethodName() + " : " + this.getNameAndTypeIndex(); } - public String getClassName(){ + + public String getClassName() { ConstantPool pool = this.getConstantPool(); - ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(this.getClassInfoIndex()); return clzInfo.getClassName(); } - public String getMethodName(){ + public String getMethodName() { ConstantPool pool = this.getConstantPool(); - NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getName(); } + + @Override + public void visitClassInfo(ClassInfo info) { + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("\t# = Methodref\t\t\t#") + .append(classInfoIndex) + .append(".#") + .append(nameAndTypeIndex) + .append("\t\t// ") + .append(getClassName() + ".") + .append(((NameAndTypeInfo) getConstantInfo(nameAndTypeIndex)).getName()) + .append(".") + .append(((NameAndTypeInfo) getConstantInfo(nameAndTypeIndex)).getTypeInfo()); + System.out.println(sb.toString()); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + + } + + @Override + public void visitString(StringInfo info) { + + } + + @Override + public void visistUTF8(UTF8Info info) { + + } } diff --git a/group17/785396327/4.5/constant/NameAndTypeInfo.java b/group17/785396327/4.5/constant/NameAndTypeInfo.java index f59efe07c0..ffb50f622a 100644 --- a/group17/785396327/4.5/constant/NameAndTypeInfo.java +++ b/group17/785396327/4.5/constant/NameAndTypeInfo.java @@ -29,6 +29,11 @@ public int getType() { return type; } + @Override + public void accept(Visitor visitor) { + + } + public String getName(){ ConstantPool pool = this.getConstantPool(); diff --git a/group17/785396327/4.5/constant/NullConstantInfo.java b/group17/785396327/4.5/constant/NullConstantInfo.java index c6bc0c17e5..e11e114840 100644 --- a/group17/785396327/4.5/constant/NullConstantInfo.java +++ b/group17/785396327/4.5/constant/NullConstantInfo.java @@ -11,4 +11,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group17/785396327/4.5/constant/StringInfo.java b/group17/785396327/4.5/constant/StringInfo.java index 595eed7f47..2da9f3a9c5 100644 --- a/group17/785396327/4.5/constant/StringInfo.java +++ b/group17/785396327/4.5/constant/StringInfo.java @@ -14,6 +14,11 @@ public int getType() { return type; } + @Override + public void accept(Visitor visitor) { + + } + public int getIndex() { return index; } diff --git a/group17/785396327/4.5/constant/UTF8Info.java b/group17/785396327/4.5/constant/UTF8Info.java index 12b8395559..8cf71cc4dc 100644 --- a/group17/785396327/4.5/constant/UTF8Info.java +++ b/group17/785396327/4.5/constant/UTF8Info.java @@ -19,6 +19,12 @@ public void setLength(int length) { public int getType() { return type; } + + @Override + public void accept(Visitor visitor) { + + } + @Override public String toString() { return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; From fb66d26cfff5329acff360ff059657bc7cd77f72 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Fri, 21 Apr 2017 21:12:20 +0800 Subject: [PATCH 086/151] update min-jvm --- .../src/com/donaldy/jvm/attr/CodeAttr.java | 47 ++++--- .../donaldy/jvm/attr/LocalVariableTable.java | 23 +++- .../src/com/donaldy/jvm/clz/ClassFile.java | 14 +- .../src/com/donaldy/jvm/cmd/BiPushCmd.java | 23 ++++ .../com/donaldy/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++++ .../com/donaldy/jvm/cmd/CommandParser.java | 85 ++++++++++++ .../src/com/donaldy/jvm/cmd/GetFieldCmd.java | 22 +++ .../donaldy/jvm/cmd/GetStaticFieldCmd.java | 23 ++++ .../com/donaldy/jvm/cmd/InvokeSpecialCmd.java | 23 ++++ .../com/donaldy/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../src/com/donaldy/jvm/cmd/LdcCmd.java | 29 ++++ .../src/com/donaldy/jvm/cmd/NewObjectCmd.java | 19 +++ .../src/com/donaldy/jvm/cmd/NoOperandCmd.java | 23 ++++ .../com/donaldy/jvm/cmd/OneOperandCmd.java | 27 ++++ .../src/com/donaldy/jvm/cmd/PutFieldCmd.java | 19 +++ .../com/donaldy/jvm/cmd/TwoOperandCmd.java | 67 +++++++++ .../src/com/donaldy/jvm/method/Method.java | 21 +++ .../donaldy/jvm/print/ClassFilePrinter.java | 54 ++++++++ .../jvm/print/ConstantPoolPrinter.java | 25 ++++ .../donaldy/jvm/test/ClassFileloaderTest.java | 84 ++++++++++++ 20 files changed, 753 insertions(+), 25 deletions(-) create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/OneOperandCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java create mode 100644 group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java create mode 100644 group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java diff --git a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java index 6b699e6991..22e48645be 100644 --- a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java +++ b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java @@ -1,6 +1,7 @@ package com.donaldy.jvm.attr; import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.cmd.ByteCodeCommand; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.loader.ByteCodeIterator; @@ -14,21 +15,21 @@ 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) { @@ -36,21 +37,33 @@ public void setLineNumberTable(LineNumberTable t) { } public void setLocalVariableTable(LocalVariableTable t) { - this.localVarTable = t; + this.localVarTable = t; } - + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ - - + return null; } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + //buffer.append("Code:").append(code).append("\n"); + for(int i=0;i items = new ArrayList(); - + public LocalVariableTable(int attrNameIndex, int attrLen) { - super(attrNameIndex, attrLen); + super(attrNameIndex, attrLen); } - + public static LocalVariableTable parse(ByteCodeIterator iter){ int attrNameIndex = iter.nextU2ToInt(); int attrLen = iter.nextU4ToInt(); @@ -38,8 +38,19 @@ public static LocalVariableTable parse(ByteCodeIterator iter){ return lvTable; } private void addLocalVariableItem(LocalVariableItem item) { - this.items.add(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(); } - - } diff --git a/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java b/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java index c36e1940b1..df5d9a0f9b 100644 --- a/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java +++ b/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java @@ -80,13 +80,23 @@ public void print(){ } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.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(); } + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..266edbc5e8 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.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(); + } + + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java b/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..48ded9618a --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.donaldy.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.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); +} diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java b/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..407040f102 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.donaldy.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.donaldy.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(); + } + + } +} diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..9fe5244f8a --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..21236d26c6 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ClassInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; +import com.donaldy.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); + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..7b56e9009b --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.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); + } + + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..58e1d1ff5e --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..28fe64a88d --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..27c8cd13ca --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..40d11a7bce --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/OneOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..9a1709a9c7 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..4b3b8c1fab --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..1d38c8ed3f --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.donaldy.jvm.cmd; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ClassInfo; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/method/Method.java b/group24/448641125/src/com/donaldy/jvm/method/Method.java index a69ff696b8..603e773b87 100644 --- a/group24/448641125/src/com/donaldy/jvm/method/Method.java +++ b/group24/448641125/src/com/donaldy/jvm/method/Method.java @@ -2,6 +2,7 @@ import com.donaldy.jvm.attr.*; import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.cmd.ByteCodeCommand; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.UTF8Info; import com.donaldy.jvm.loader.ByteCodeIterator; @@ -86,4 +87,24 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return method; } + + 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 ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java b/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..26e9d183d4 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java @@ -0,0 +1,54 @@ +package com.donaldy.jvm.print; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ClassInfo; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; +import com.donaldy.jvm.constant.MethodRefInfo; +import com.donaldy.jvm.constant.NameAndTypeInfo; + +import com.donaldy.jvm.constant.StringInfo; +import com.donaldy.jvm.constant.UTF8Info; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java b/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..7070d5766e --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,25 @@ +package com.donaldy.jvm.print; + +import com.donaldy.jvm.constant.ClassInfo; +import com.donaldy.jvm.constant.ConstantInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; +import com.donaldy.jvm.constant.MethodRefInfo; +import com.donaldy.jvm.constant.NameAndTypeInfo; +import com.donaldy.jvm.constant.StringInfo; +import com.donaldy.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java index 8610fda4c9..0884878010 100644 --- a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java +++ b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java @@ -2,6 +2,10 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.clz.ClassIndex; +import com.donaldy.jvm.cmd.BiPushCmd; +import com.donaldy.jvm.cmd.ByteCodeCommand; +import com.donaldy.jvm.cmd.OneOperandCmd; +import com.donaldy.jvm.cmd.TwoOperandCmd; import com.donaldy.jvm.constant.*; import com.donaldy.jvm.field.Field; import com.donaldy.jvm.method.Method; @@ -276,4 +280,84 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedCode, code); } + + /** + * 第四次 JVM作业 + */ + + @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 c2bdaa8ba49db9af61fc05997e502333e51a6440 Mon Sep 17 00:00:00 2001 From: Haochen Date: Fri, 21 Apr 2017 21:20:36 +0800 Subject: [PATCH 087/151] modify InfixExpr using Token & TokenParser --- .../java/algorithm/expression/InfixExpr.java | 94 ++++--------------- .../algorithm/expression/InfixExprTest.java | 3 +- 2 files changed, 17 insertions(+), 80 deletions(-) diff --git a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java index ad4fae505b..8ab94a5093 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java @@ -7,63 +7,41 @@ public class InfixExpr { - Stack numbers = new Stack(); - Stack operators = new Stack(); + private Stack numbers = new Stack(); + private Stack operators = new Stack(); - String expr = null; + private String expr = null; public InfixExpr(String expr) { this.expr = expr; operators.push("#"); } - public float evaluate() throws CalculateException { + public float evaluate() { numbers.clear(); operators.clear(); operators.push("#"); - String[] split = split(expr); - String[] strs = new String[split.length + 1]; - strs[strs.length - 1] = "#"; - System.arraycopy(split, 0, strs, 0, split.length); + List tokens = TokenParser.parse(expr); + tokens.add(new Token(Token.OPERATOR, "#")); - for (int i = 0; !operators.isEmpty() && i < strs.length; ++i) { - String str = strs[i]; - try { - float number = Float.parseFloat(str); - putNumber(number); - } catch (NumberFormatException e) { - putOperator(str); + for (int i = 0; !operators.isEmpty() && i < tokens.size(); ++i) { + Token token = tokens.get(i); + if (token.isNumber()) { + putNumber(token.getFloatValue()); + } else { + putOperator(token.toString()); } } return numbers.isEmpty() ? 0 : (float) numbers.peek(); } - private String[] split(String expr) { - List list = new ArrayList<>(); - int startPos = 0; - for (int i = 0, j = 1; j < expr.length(); ++i, ++j) { - char cI = expr.charAt(i); - char cJ = expr.charAt(j); - if (isDigit(cI) ^ isDigit(cJ)) { - list.add(expr.substring(startPos, j)); - startPos = j; - } - } - list.add(expr.substring(startPos)); - return list.toArray(new String[list.size()]); - } - - private boolean isDigit(char c) { - return Character.isDigit(c) || c == '.'; - } - private void putNumber(float num) { numbers.push(num); } - private void putOperator(String op) throws CalculateException { - int compare = compare(op, (String) operators.peek()); + private void putOperator(String op) { + int compare = Token.compare(op, (String) operators.peek()); switch (compare) { case 1: operators.push(op); @@ -82,7 +60,7 @@ private void putOperator(String op) throws CalculateException { } } - private float calculate(float num2, String op, float num1) throws CalculateException { + private float calculate(float num2, String op, float num1) { switch (op) { case "+": return num2 + num1; @@ -95,46 +73,6 @@ private float calculate(float num2, String op, float num1) throws CalculateExcep return num2 / num1; } } - throw new CalculateException(); - } - - private int compare(String op, String peek) { - int opIndex = indexOf(op); - int peekIndex = indexOf(peek); - return table[opIndex][peekIndex]; - } - - private int indexOf(String op) { - switch (op) { - case "+": - return 0; - case "-": - return 1; - case "*": - return 2; - case "/": - return 3; - case "(": - return 4; - case ")": - return 5; - case "#": - return 6; - } - return 0; + throw new RuntimeException("Divide by 0"); } - - //优先级表 - private int[][] table = { - // + - * / ( ) # - {-1, -1, -1, -1, 1, -1, 1}, // + - {-1, -1, -1, -1, 1, -1, 1}, // - - { 1, 1, -1, -1, 1, -1, 1}, // * - { 1, 1, -1, -1, 1, -1, 1}, // / - { 1, 1, 1, 1, 1, -1, 1}, // ( - {-1, -1, -1, -1, -1, 0, 1}, // ) - {-1, -1, -1, -1, -1, -1, 0} // # - }; - - public static class CalculateException extends Exception {} } diff --git a/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java b/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java index e4c63b79f7..f46783f4d0 100644 --- a/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java +++ b/group01/895457260/code/src/test/java/algorithm/expression/InfixExprTest.java @@ -17,8 +17,7 @@ public void tearDown() throws Exception { } @Test - public void testEvaluate() throws InfixExpr.CalculateException { - //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + public void testEvaluate() throws Exception { { InfixExpr expr = new InfixExpr("2+3*4+5"); Assert.assertEquals(19.0, expr.evaluate(), 0.001f); From 44e05805ebf6e5c2c0d2066677d79779efac2b7b Mon Sep 17 00:00:00 2001 From: Haochen Date: Fri, 21 Apr 2017 21:40:38 +0800 Subject: [PATCH 088/151] make InfixExpr to ignore invisiable chars --- .../code/src/main/java/algorithm/expression/InfixExpr.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java index 8ab94a5093..d779244b58 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java @@ -10,10 +10,10 @@ public class InfixExpr { private Stack numbers = new Stack(); private Stack operators = new Stack(); - private String expr = null; - + private String expr; + public InfixExpr(String expr) { - this.expr = expr; + this.expr = expr.replaceAll("\\s", ""); operators.push("#"); } From 8bcfc5e8a355671ea50c7de00db97ced8ebc8103 Mon Sep 17 00:00:00 2001 From: Haochen Date: Fri, 21 Apr 2017 22:37:12 +0800 Subject: [PATCH 089/151] refactor InfixExpr --- .../java/algorithm/expression/InfixExpr.java | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java index d779244b58..5f8bd1f318 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixExpr.java @@ -14,34 +14,33 @@ public class InfixExpr { public InfixExpr(String expr) { this.expr = expr.replaceAll("\\s", ""); - operators.push("#"); } public float evaluate() { numbers.clear(); operators.clear(); - operators.push("#"); + operators.push(Token.SCOPE); List tokens = TokenParser.parse(expr); - tokens.add(new Token(Token.OPERATOR, "#")); + tokens.add(Token.SCOPE); - for (int i = 0; !operators.isEmpty() && i < tokens.size(); ++i) { + for (int i = 0; i < tokens.size() && !operators.isEmpty(); ++i) { Token token = tokens.get(i); if (token.isNumber()) { - putNumber(token.getFloatValue()); + putNumber(token); } else { - putOperator(token.toString()); + putOperator(token); } } - return numbers.isEmpty() ? 0 : (float) numbers.peek(); + return numbers.isEmpty() ? 0 : ((Token) numbers.peek()).getFloatValue(); } - private void putNumber(float num) { + private void putNumber(Token num) { numbers.push(num); } - private void putOperator(String op) { - int compare = Token.compare(op, (String) operators.peek()); + private void putOperator(Token op) { + int compare = Token.compare(op, (Token) operators.peek()); switch (compare) { case 1: operators.push(op); @@ -50,29 +49,13 @@ private void putOperator(String op) { operators.pop(); break; case -1: - float num1 = (float) numbers.pop(); - float num2 = (float) numbers.pop(); - String operator = (String) operators.pop(); - float result = calculate(num2, operator, num1); + Token num1 = (Token) numbers.pop(); + Token num2 = (Token) numbers.pop(); + Token operator = (Token) operators.pop(); + Token result = Token.calculate(num2, operator, num1); numbers.push(result); putOperator(op); break; } } - - private float calculate(float num2, String op, float num1) { - switch (op) { - case "+": - return num2 + num1; - case "-": - return num2 - num1; - case "*": - return num2 * num1; - case "/": - if (num1 != 0) { - return num2 / num1; - } - } - throw new RuntimeException("Divide by 0"); - } } From a806293f293741b3654383c2110cda1d581210e7 Mon Sep 17 00:00:00 2001 From: Haochen Date: Fri, 21 Apr 2017 22:38:30 +0800 Subject: [PATCH 090/151] finish PostfixExpr --- .../algorithm/expression/PostfixExpr.java | 46 +++++++++++++++++++ .../algorithm/expression/PostfixExprTest.java | 37 +++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java create mode 100644 group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java diff --git a/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java new file mode 100644 index 0000000000..6614d0ec7d --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java @@ -0,0 +1,46 @@ +package algorithm.expression; + +import datastructure.basic.Stack; + +import java.util.EmptyStackException; +import java.util.List; + +public class PostfixExpr { + + private String expr; + private String splitRegex; + private Stack stack = new Stack(); + + public PostfixExpr(String expr) { + this.expr = expr; + this.splitRegex = " "; + } + + public PostfixExpr(String expr, String splitRegex) { + this.expr = expr; + this.splitRegex = splitRegex; + } + + public float evaluate() { + stack.clear(); + List tokens = TokenParser.parse(expr, splitRegex); + + try { + for (Token token : tokens) { + if (token.isNumber()) { + stack.push(token); + } else { + Token num1 = (Token) stack.pop(); + Token num2 = (Token) stack.pop(); + stack.push(Token.calculate(num2, token, num1)); + } + } + } catch (EmptyStackException e) { + throw new RuntimeException("Wrong expression: " + expr); + } + if (stack.size() != 1) { + throw new RuntimeException("Wrong expression: " + expr); + } + return ((Token) stack.pop()).getFloatValue(); + } +} diff --git a/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java b/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java new file mode 100644 index 0000000000..d57f19fcda --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java @@ -0,0 +1,37 @@ +package algorithm.expression; + +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); + } + } + +} From c32d8936565552b3e50ac222899c3d88ea79f740 Mon Sep 17 00:00:00 2001 From: Haochen Date: Fri, 21 Apr 2017 22:38:57 +0800 Subject: [PATCH 091/151] finish PrefixExpr --- .../algorithm/expression/InfixToPostfix.java | 14 +++ .../java/algorithm/expression/PrefixExpr.java | 47 ++++++++ .../main/java/algorithm/expression/Token.java | 106 ++++++++++++++++++ .../algorithm/expression/TokenParser.java | 53 +++++++++ .../main/java/jvm/print/ClassFilePrinter.java | 44 ++++++++ .../java/jvm/print/ConstantPoolPrinter.java | 15 +++ .../algorithm/expression/PrefixExprTest.java | 44 ++++++++ .../algorithm/expression/TokenParserTest.java | 39 +++++++ 8 files changed, 362 insertions(+) create mode 100644 group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java create mode 100644 group01/895457260/code/src/main/java/algorithm/expression/PrefixExpr.java create mode 100644 group01/895457260/code/src/main/java/algorithm/expression/Token.java create mode 100644 group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java create mode 100644 group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java create mode 100644 group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java create mode 100644 group01/895457260/code/src/test/java/algorithm/expression/PrefixExprTest.java create mode 100644 group01/895457260/code/src/test/java/algorithm/expression/TokenParserTest.java diff --git a/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java new file mode 100644 index 0000000000..58ffe99cd3 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java @@ -0,0 +1,14 @@ +package algorithm.expression; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} diff --git a/group01/895457260/code/src/main/java/algorithm/expression/PrefixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/PrefixExpr.java new file mode 100644 index 0000000000..2b70fab0a3 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/expression/PrefixExpr.java @@ -0,0 +1,47 @@ +package algorithm.expression; + +import datastructure.basic.Stack; + +import java.util.EmptyStackException; +import java.util.List; + +public class PrefixExpr { + private String expr; + private String splitRegex; + private Stack stack = new Stack(); + + public PrefixExpr(String expr) { + this.expr = expr; + this.splitRegex = " "; + } + + public PrefixExpr(String expr, String splitRegex) { + this.expr = expr; + this.splitRegex = splitRegex; + } + + public float evaluate() { + stack.clear(); + List tokens = TokenParser.parse(expr, splitRegex); + + try { + for (int i = tokens.size() - 1; i >= 0; --i) { + Token token = tokens.get(i); + if (token.isNumber()) { + stack.push(token); + } else { + Token num1 = (Token) stack.pop(); + Token num2 = (Token) stack.pop(); + Token result = Token.calculate(num1, token, num2); + stack.push(result); + } + } + } catch (EmptyStackException e) { + throw new RuntimeException("Wrong expression: " + expr); + } + if (stack.size() != 1) { + throw new RuntimeException("Wrong expression: " + expr); + } + return ((Token) stack.pop()).getFloatValue(); + } +} diff --git a/group01/895457260/code/src/main/java/algorithm/expression/Token.java b/group01/895457260/code/src/main/java/algorithm/expression/Token.java new file mode 100644 index 0000000000..3aa4f6f9c4 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/expression/Token.java @@ -0,0 +1,106 @@ +package algorithm.expression; + +import java.util.Arrays; +import java.util.List; + +class Token { + public static final String ADD = "+"; + public static final String SUB = "-"; + public static final String MUL = "*"; + public static final String DIV = "/"; + public static final String L_BRACKET = "("; + public static final String R_BRACKET = ")"; + + public static final List OPERATORS = Arrays.asList(ADD, SUB, MUL, DIV, L_BRACKET, R_BRACKET); + public static final int OPERATOR = 1; + public static final int NUMBER = 2; + + public static final String SCOPE_STR = "#"; + public static final Token SCOPE = new Token(OPERATOR, SCOPE_STR); + + //优先级表 + private static int[][] priorities = { + // + - * / ( ) # + {-1, -1, -1, -1, 1, -1, 1}, // + + {-1, -1, -1, -1, 1, -1, 1}, // - + { 1, 1, -1, -1, 1, -1, 1}, // * + { 1, 1, -1, -1, 1, -1, 1}, // / + { 1, 1, 1, 1, 1, -1, 1}, // ( + {-1, -1, -1, -1, -1, 0, 1}, // ) + {-1, -1, -1, -1, -1, -1, 0} // # + }; + + 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.valueOf(value); + } + + public String toString(){ + return value; + } + + private static int indexOf(String op) { + switch (op) { + case ADD: + return 0; + case SUB: + return 1; + case MUL: + return 2; + case DIV: + return 3; + case L_BRACKET: + return 4; + case R_BRACKET: + return 5; + case SCOPE_STR: + return 6; + } + return 0; + } + + public static int compare(Token op, Token peek) { + int opIndex = indexOf(op.toString()); + int peekIndex = indexOf(peek.toString()); + return priorities[opIndex][peekIndex]; + } + + public static Token calculate(Token num1, Token op, Token num2) { + float result = 0.0f; + float n1 = num1.getFloatValue(); + float n2 = num2.getFloatValue(); + switch (op.toString()) { + case "+": + result = n1 + n2; + break; + case "-": + result = n1 - n2; + break; + case "*": + result = n1 * n2; + break; + case "/": + if (n2 == 0) { + throw new RuntimeException("Divide by 0"); + } + result = n1 / n2; + break; + } + return new Token(NUMBER, result + ""); + } +} \ No newline at end of file diff --git a/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java new file mode 100644 index 0000000000..fc146579bd --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java @@ -0,0 +1,53 @@ +package algorithm.expression; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + public static List parse(String expression) { + return parse(expression, null); + } + + public static List parse(String expression, String splitRegex) { + List tokens = new ArrayList<>(); + String[] split = splitRegex == null || "".equals(splitRegex) ? + new String[]{expression} : expression.split(splitRegex); + + for (String expr : split) { + 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 static int indexOfNextOperator(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + } + + private static boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..632f36c2ea --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java @@ -0,0 +1,44 @@ +package jvm.print; + +import jvm.ClassFileLoader; +import jvm.classfile.ClassFile; +import jvm.exception.ReadClassException; + +public class ClassFilePrinter { + ClassFile clzFile; + + 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.getMajorVersion()); + + ConstantPoolPrinter poolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + poolPrinter.print(); + } + + public static void main(String[] args) { + String path = "target/test-classes"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "jvm.EmployeeV1"; + + ClassFile clzFile = null; + try { + clzFile = loader.load(className); + } catch (ReadClassException e) { + e.printStackTrace(); + } + if (clzFile != null) { + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + printer.print(); + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java b/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..e528f351ad --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,15 @@ +package jvm.print; + +import jvm.classfile.ConstantPool; + +public class ConstantPoolPrinter { + ConstantPool pool; + + ConstantPoolPrinter(ConstantPool pool) { + this.pool = pool; + } + + public void print() { + System.out.println("Constant Pool:"); + } +} diff --git a/group01/895457260/code/src/test/java/algorithm/expression/PrefixExprTest.java b/group01/895457260/code/src/test/java/algorithm/expression/PrefixExprTest.java new file mode 100644 index 0000000000..a3aa9860f0 --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/expression/PrefixExprTest.java @@ -0,0 +1,44 @@ +package algorithm.expression; + +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/group01/895457260/code/src/test/java/algorithm/expression/TokenParserTest.java b/group01/895457260/code/src/test/java/algorithm/expression/TokenParserTest.java new file mode 100644 index 0000000000..b2a7aec54e --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/expression/TokenParserTest.java @@ -0,0 +1,39 @@ +package algorithm.expression; + +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).getFloatValue()); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getFloatValue()); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getFloatValue()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getFloatValue()); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getFloatValue()); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getFloatValue()); + } + +} From ca83f609a5a94239338689d30ad2d2b87adf3ab5 Mon Sep 17 00:00:00 2001 From: gongxun Date: Fri, 21 Apr 2017 23:34:18 +0800 Subject: [PATCH 092/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4.16/print/ClassFilePrinter.java | 48 +++++++++++++++++++ .../4.16/print/ConstantPoolPrinter.java | 48 +++++++++++++++++++ group17/785396327/4.5/clz/ClassFile.java | 7 ++- .../785396327/4.5/constant/ConstantPool.java | 1 + .../785396327/4.5/constant/MethodRefInfo.java | 41 +--------------- .../4.5/constant/NameAndTypeInfo.java | 20 ++++---- .../4.5/constant/NullConstantInfo.java | 1 + .../785396327/4.5/constant/StringInfo.java | 2 +- 8 files changed, 117 insertions(+), 51 deletions(-) create mode 100644 group17/785396327/4.16/print/ClassFilePrinter.java create mode 100644 group17/785396327/4.16/print/ConstantPoolPrinter.java diff --git a/group17/785396327/4.16/print/ClassFilePrinter.java b/group17/785396327/4.16/print/ClassFilePrinter.java new file mode 100644 index 0000000000..2c2b49bab0 --- /dev/null +++ b/group17/785396327/4.16/print/ClassFilePrinter.java @@ -0,0 +1,48 @@ +package print; + +import clz.ClassFile; +import jvm_1.ClassFileLoader; + +/** + * Created by gongxun on 2017/4/21. + */ +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/group17/785396327/4.16/print/ConstantPoolPrinter.java b/group17/785396327/4.16/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..9e17cc1ff2 --- /dev/null +++ b/group17/785396327/4.16/print/ConstantPoolPrinter.java @@ -0,0 +1,48 @@ +package print; + +import constant.*; + +/** + * Created by gongxun on 2017/4/21. + */ +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + @Override + public void visitClassInfo(ClassInfo info) { + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + + } + + @Override + public void visitString(StringInfo info) { + + } + + @Override + public void visistUTF8(UTF8Info info) { + + } + }; + } +} diff --git a/group17/785396327/4.5/clz/ClassFile.java b/group17/785396327/4.5/clz/ClassFile.java index fe3f0f500e..f53199e6bb 100644 --- a/group17/785396327/4.5/clz/ClassFile.java +++ b/group17/785396327/4.5/clz/ClassFile.java @@ -1,6 +1,7 @@ package clz; import constant.ClassInfo; +import constant.ConstantInfo; import constant.ConstantPool; import field.Field; import method.Method; @@ -79,15 +80,17 @@ public void print(){ System.out.println("Super Class Name:"+ getSuperClassName()); + System.out.println("Constant pool:"); + } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.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(); } diff --git a/group17/785396327/4.5/constant/ConstantPool.java b/group17/785396327/4.5/constant/ConstantPool.java index b7b29bf115..396ccee230 100644 --- a/group17/785396327/4.5/constant/ConstantPool.java +++ b/group17/785396327/4.5/constant/ConstantPool.java @@ -28,4 +28,5 @@ public String getUTF8String(int index){ public Object getSize() { return this.constantInfos.size() -1; } + } diff --git a/group17/785396327/4.5/constant/MethodRefInfo.java b/group17/785396327/4.5/constant/MethodRefInfo.java index 78b6cf74e7..7a95d2a6bb 100644 --- a/group17/785396327/4.5/constant/MethodRefInfo.java +++ b/group17/785396327/4.5/constant/MethodRefInfo.java @@ -3,7 +3,7 @@ /** * Created by IBM on 2017/4/10. */ -public class MethodRefInfo extends ConstantInfo implements ConstantInfo.Visitor { +public class MethodRefInfo extends ConstantInfo{ private int type = ConstantInfo.METHOD_INFO; private int classInfoIndex; @@ -55,43 +55,4 @@ public String getMethodName() { return typeInfo.getName(); } - @Override - public void visitClassInfo(ClassInfo info) { - - } - - @Override - public void visitFieldRef(FieldRefInfo info) { - - } - - @Override - public void visitMethodRef(MethodRefInfo info) { - StringBuilder sb = new StringBuilder(); - sb.append("\t# = Methodref\t\t\t#") - .append(classInfoIndex) - .append(".#") - .append(nameAndTypeIndex) - .append("\t\t// ") - .append(getClassName() + ".") - .append(((NameAndTypeInfo) getConstantInfo(nameAndTypeIndex)).getName()) - .append(".") - .append(((NameAndTypeInfo) getConstantInfo(nameAndTypeIndex)).getTypeInfo()); - System.out.println(sb.toString()); - } - - @Override - public void visitNameAndType(NameAndTypeInfo info) { - - } - - @Override - public void visitString(StringInfo info) { - - } - - @Override - public void visistUTF8(UTF8Info info) { - - } } diff --git a/group17/785396327/4.5/constant/NameAndTypeInfo.java b/group17/785396327/4.5/constant/NameAndTypeInfo.java index ffb50f622a..a65456d245 100644 --- a/group17/785396327/4.5/constant/NameAndTypeInfo.java +++ b/group17/785396327/4.5/constant/NameAndTypeInfo.java @@ -4,8 +4,7 @@ * Created by IBM on 2017/4/10. */ public class NameAndTypeInfo extends ConstantInfo { - public int type = ConstantInfo.NAME_AND_TYPE_INFO; - + public int type = ConstantInfo.NAME_AND_TYPE_INFO; private int index1; private int index2; @@ -16,15 +15,19 @@ public NameAndTypeInfo(ConstantPool pool) { public int getIndex1() { return index1; } + public void setIndex1(int index1) { this.index1 = index1; } + public int getIndex2() { return index2; } + public void setIndex2(int index2) { this.index2 = index2; } + public int getType() { return type; } @@ -35,19 +38,20 @@ public void accept(Visitor visitor) { } - public String getName(){ + public String getName() { ConstantPool pool = this.getConstantPool(); - UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + UTF8Info utf8Info1 = (UTF8Info) pool.getConstantInfo(index1); return utf8Info1.getValue(); } - public String getTypeInfo(){ + public String getTypeInfo() { ConstantPool pool = this.getConstantPool(); - UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + UTF8Info utf8Info2 = (UTF8Info) pool.getConstantInfo(index2); return utf8Info2.getValue(); } - public String toString(){ - return "(" + getName() + "," + getTypeInfo()+")"; + public String toString() { + return "(" + getName() + "," + getTypeInfo() + ")"; } + } diff --git a/group17/785396327/4.5/constant/NullConstantInfo.java b/group17/785396327/4.5/constant/NullConstantInfo.java index e11e114840..f3b1201e3a 100644 --- a/group17/785396327/4.5/constant/NullConstantInfo.java +++ b/group17/785396327/4.5/constant/NullConstantInfo.java @@ -16,4 +16,5 @@ public int getType() { public void accept(Visitor visitor) { } + } diff --git a/group17/785396327/4.5/constant/StringInfo.java b/group17/785396327/4.5/constant/StringInfo.java index 2da9f3a9c5..6953e7cdf8 100644 --- a/group17/785396327/4.5/constant/StringInfo.java +++ b/group17/785396327/4.5/constant/StringInfo.java @@ -16,7 +16,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + visitor.visitString(this); } public int getIndex() { From 8324f2289f9d634b5e6927072f93fd98e714e162 Mon Sep 17 00:00:00 2001 From: "kaitao.li" Date: Fri, 21 Apr 2017 23:40:31 +0800 Subject: [PATCH 093/151] =?UTF-8?q?jvm=E7=AC=AC=E4=B8=89=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A,=20=E8=BF=90=E7=AE=97=E5=BC=8F=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExpr.java | 155 ++++++++++++++++-- 1 file changed, 141 insertions(+), 14 deletions(-) diff --git a/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java index 0f95b519dd..83eee7e6a5 100644 --- a/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java +++ b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java @@ -1,18 +1,145 @@ package com.coding2017.basic.stack.expr; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; +import java.util.stream.Collectors; + +import com.google.common.base.CharMatcher; +import com.google.common.collect.Lists; + public class InfixExpr { - String expr = null; - - public InfixExpr(String expr) { - this.expr = expr; - } - - public float evaluate() { - - return 0.0f; - } - - - - + private static final CharMatcher CHAR_MATCHER = CharMatcher.anyOf(Operator.allOperator()); + + private Stack operatorStack = new Stack<>(); + private Stack numberStack = new Stack<>(); + + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List list = splitByOperator(expr); + for (String s : list) { + if (Operator.isOperator(s)) { + if (operatorStack.isEmpty()) { + operatorStack.push(s); + } else { + while (true) { + String op = operatorStack.peek(); + if (Operator.opOf(op).getPriority() >= Operator.opOf(s).getPriority()) { + calculateOnce(); + } else { + break; + } + if (operatorStack.isEmpty()) { + break; + } + } + operatorStack.push(s); + } + } else { + numberStack.push(Float.parseFloat(s)); + } + } + while (!operatorStack.isEmpty()) { + calculateOnce(); + } + if (numberStack.isEmpty() || numberStack.size() != 1) { + throw new RuntimeException("expr error"); + } + return numberStack.pop(); + } + + private void calculateOnce() { + String operator = operatorStack.pop(); + Float secondNumber = numberStack.pop(); + Float firstNumber = numberStack.pop(); + Float calculate = calculate(firstNumber, secondNumber, operator); + numberStack.push(calculate); + } + + private Float calculate(Float firstNumber, Float seconfNumber, String operator) { + if (Operator.ADD.getOp().equals(operator)) { + return firstNumber + seconfNumber; + } else if (Operator.MINUTE.getOp().equals(operator)) { + return firstNumber - seconfNumber; + } else if (Operator.MULTIPLY.getOp().equals(operator)) { + return firstNumber * seconfNumber; + } else if (Operator.DIVIDE.getOp().equals(operator)) { + return firstNumber / seconfNumber; + } + return null; + } + + private List splitByOperator(String expr) { + int pos = 0; + List list = Lists.newArrayList(); + while (pos < expr.length()) { + int index = CHAR_MATCHER.indexIn(expr, pos); + if (index < 0) { + list.add(expr.substring(pos).trim()); + pos = expr.length(); + } else { + list.add(expr.substring(pos, index).trim()); + list.add(expr.substring(index, index + 1)); + pos = index + 1; + } + } + return list; + } + + enum Operator { + ADD("+", 1), MINUTE("-", 1), MULTIPLY("*", 2), DIVIDE("/", 2); + + private String op; + private int priority; + + Operator(String op, int priority) { + this.op = op; + this.priority = priority; + } + + public static Operator opOf(String op) { + for (Operator operator : values()) { + if (operator.getOp().equals(op)) { + return operator; + } + } + return null; + } + + public static boolean isOperator(String op) { + for (Operator operator : values()) { + if (operator.getOp().equals(op)) { + return true; + } + } + return false; + } + + public static String allOperator() { + return Arrays.stream(values()).map(Operator::getOp).collect(Collectors.joining()); + } + + public String getOp() { + return op; + } + + public void setOp(String op) { + this.op = op; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + } + } From 2634c9926813101381b473aa1fed88527181b292 Mon Sep 17 00:00:00 2001 From: Haochen Date: Sat, 22 Apr 2017 00:08:30 +0800 Subject: [PATCH 094/151] add toHexString(byte[]) --- group01/895457260/code/src/main/java/jvm/util/ByteUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java index 87afccab3c..5a82776eef 100644 --- a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java +++ b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java @@ -5,6 +5,10 @@ * TODO: */ public class ByteUtils { + public static String toHexString(byte[] bytes) { + return toHexString(bytes, 0, bytes.length); + } + public static String toHexString(byte[] bytes, int off, int len) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < len; ++i) { From c9c03bc08ac548e5839d97ed039cd122170f4661 Mon Sep 17 00:00:00 2001 From: Haochen Date: Sat, 22 Apr 2017 00:10:05 +0800 Subject: [PATCH 095/151] finish constant pool printing --- .../main/java/jvm/classfile/ClassParser.java | 12 ++--- .../main/java/jvm/classfile/ConstantPool.java | 10 ++--- .../jvm/classfile/constant/item/Constant.java | 7 +++ .../constant/item/impl/ClassInfo.java | 12 +++++ .../constant/item/impl/CountConstant.java | 8 ++++ .../constant/item/impl/DoubleInfo.java | 13 ++++++ .../constant/item/impl/FieldRefInfo.java | 24 +++++++++- .../constant/item/impl/FloatInfo.java | 13 ++++++ .../constant/item/impl/IntegerInfo.java | 13 ++++++ .../item/impl/InterfaceMethodRefInfo.java | 24 +++++++++- .../constant/item/impl/InvokeDynamicInfo.java | 24 +++++++++- .../constant/item/impl/LongInfo.java | 13 ++++++ .../constant/item/impl/MethodHandleInfo.java | 16 ++++++- .../constant/item/impl/MethodRefInfo.java | 24 +++++++++- .../constant/item/impl/MethodTypeInfo.java | 22 +++++++++- .../constant/item/impl/NameAndTypeInfo.java | 28 +++++++++++- .../constant/item/impl/StringInfo.java | 12 +++++ .../constant/item/impl/UTF8Info.java | 10 +++++ .../main/java/jvm/print/ClassFilePrinter.java | 3 ++ .../java/jvm/print/ConstantPoolPrinter.java | 44 +++++++++++++++++++ 20 files changed, 315 insertions(+), 17 deletions(-) diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java index bec7317e2c..398bbaa4f2 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java @@ -104,10 +104,12 @@ private static void parseMethods(ClassFile classFile, ByteCodeIterator iterator) private static void linkConstantReferences(ClassFile classFile) { ConstantPool constantPool = classFile.constantPool; - constantPool.forEach(c -> { - if (c instanceof IReference) { - ((IReference) c).linkReference(constantPool); - } - }); + for (int i = 0; i < constantPool.getSize(); ++i) { + constantPool.forEach(c -> { + if (c instanceof IReference) { + ((IReference) c).linkReference(constantPool); + } + }); + } } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java b/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java index b077ad83a4..9c5bae83db 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java @@ -11,20 +11,20 @@ * TODO: */ public class ConstantPool { - private List constantMap = new ArrayList<>(); + private List constants = new ArrayList<>(); public void forEach(Consumer action) { - constantMap.forEach(action); + constants.forEach(action); } public int getSize() { - return constantMap.size() - 1; + return constants.size() - 1; } boolean addConstantInfo(Constant c) { - return constantMap.add(c); + return constants.add(c); } public Constant getConstantInfo(int index) { - return constantMap.get(index); + return constants.get(index); } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java index c83fbfbb28..1f87f4d495 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java @@ -1,9 +1,16 @@ package jvm.classfile.constant.item; +import java.util.Map; + /** * Created by Haochen on 2017/4/9. * TODO: */ public interface Constant { + int PRINT_TYPE = 1; + int PRINT_PARAM = 2; + int PRINT_COMMENT = 3; + int size(); + Map printableMap(); } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java index 84657cd7e4..5e588ada69 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java @@ -4,6 +4,9 @@ import jvm.classfile.constant.item.Constant; import jvm.classfile.constant.item.IReference; +import java.util.HashMap; +import java.util.Map; + /** * Created by Haochen on 2017/4/9. * TODO: @@ -21,6 +24,15 @@ public int size() { return 3; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Class"); + map.put(PRINT_PARAM, "#" + nameIndex); + map.put(PRINT_COMMENT, "// " + className); + return map; + } + @Override public void linkReference(ConstantPool constantPool) { Constant constant = constantPool.getConstantInfo(getUtf8Index()); diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java index 1d671fcbda..f2aaf98787 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java @@ -2,6 +2,9 @@ import jvm.classfile.constant.item.Constant; +import java.util.HashMap; +import java.util.Map; + /** * Created by Haochen on 2017/4/9. * TODO: @@ -18,6 +21,11 @@ public int size() { return 2; } + @Override + public Map printableMap() { + return null; + } + public int getCount() { return count; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java index 8fa38452f6..22aad3a0b8 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java @@ -1,6 +1,10 @@ package jvm.classfile.constant.item.impl; import jvm.classfile.constant.item.Constant; +import jvm.util.ByteUtils; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. @@ -20,6 +24,15 @@ public int size() { return 9; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Double"); + map.put(PRINT_PARAM, ByteUtils.toHexString(highBytes) + ByteUtils.toHexString(lowBytes)); + map.put(PRINT_COMMENT, ""); + return map; + } + public byte[] getHighBytes() { return highBytes; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java index a7f51f51ba..9bb866713b 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java @@ -1,14 +1,21 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class FieldRefInfo implements Constant { +public class FieldRefInfo implements Constant, IReference { private int classIndex; private int nameAndTypeIndex; + private String className; + private String nameAndType; public FieldRefInfo(int classIndex, int nameAndTypeIndex) { this.classIndex = classIndex; @@ -20,6 +27,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "FieldRef"); + map.put(PRINT_PARAM, "#" + classIndex + ".#" + nameAndTypeIndex); + map.put(PRINT_COMMENT, "// " + className + '.' + nameAndType); + return map; + } + public int getClassIndex() { return classIndex; } @@ -27,4 +43,10 @@ public int getClassIndex() { public int getNameAndTypeIndex() { return nameAndTypeIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + className = ((ClassInfo) constantPool.getConstantInfo(classIndex)).getClassName(); + nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java index 1368c07674..a24ea332be 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java @@ -1,6 +1,10 @@ package jvm.classfile.constant.item.impl; import jvm.classfile.constant.item.Constant; +import jvm.util.ByteUtils; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. @@ -18,6 +22,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Float"); + map.put(PRINT_PARAM, ByteUtils.toHexString(bytes)); + map.put(PRINT_COMMENT, ""); + return map; + } + public byte[] getBytes() { return bytes; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java index e345f94994..b929c36a97 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java @@ -1,6 +1,10 @@ package jvm.classfile.constant.item.impl; import jvm.classfile.constant.item.Constant; +import jvm.util.ByteUtils; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. @@ -18,6 +22,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Integer"); + map.put(PRINT_PARAM, ByteUtils.toHexString(bytes)); + map.put(PRINT_COMMENT, ""); + return map; + } + public byte[] getBytes() { return bytes; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java index e22f8d4a45..83cbc3dbc1 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java @@ -1,14 +1,21 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class InterfaceMethodRefInfo implements Constant { +public class InterfaceMethodRefInfo implements Constant, IReference { private int classIndex; private int nameAndTypeIndex; + private String className; + private String nameAndType; public InterfaceMethodRefInfo(int classIndex, int nameAndTypeIndex) { this.classIndex = classIndex; @@ -20,6 +27,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "InterfaceMethod"); + map.put(PRINT_PARAM, "#" + classIndex + ".#" + nameAndTypeIndex); + map.put(PRINT_COMMENT, "// " + className + '.' + nameAndType); + return map; + } + public int getClassIndex() { return classIndex; } @@ -27,4 +43,10 @@ public int getClassIndex() { public int getNameAndTypeIndex() { return nameAndTypeIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + className = ((ClassInfo) constantPool.getConstantInfo(classIndex)).getClassName(); + nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java index 91caadbb46..11bab7c6ed 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java @@ -1,14 +1,21 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class InvokeDynamicInfo implements Constant { +public class InvokeDynamicInfo implements Constant, IReference { private int bootstrapMethodAttrIndex; private int nameAndTypeIndex; + private String bootstrapMethodAttr; + private String nameAndType; public InvokeDynamicInfo(int bootstrapMethodAttrIndex, int nameAndTypeIndex) { this.bootstrapMethodAttrIndex = bootstrapMethodAttrIndex; @@ -20,6 +27,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "InvokeDynamic"); + map.put(PRINT_PARAM, "#" + bootstrapMethodAttrIndex + ".#" + nameAndTypeIndex); + map.put(PRINT_COMMENT, "// " + bootstrapMethodAttr + '.' + nameAndType); + return map; + } + public int getBootstrapMethodAttrIndex() { return bootstrapMethodAttrIndex; } @@ -27,4 +43,10 @@ public int getBootstrapMethodAttrIndex() { public int getNameAndTypeIndex() { return nameAndTypeIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + bootstrapMethodAttr = ((ClassInfo) constantPool.getConstantInfo(bootstrapMethodAttrIndex)).getClassName(); + nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java index c740e39f30..202110fb01 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java @@ -1,6 +1,10 @@ package jvm.classfile.constant.item.impl; import jvm.classfile.constant.item.Constant; +import jvm.util.ByteUtils; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. @@ -20,6 +24,15 @@ public int size() { return 9; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Long"); + map.put(PRINT_PARAM, ByteUtils.toHexString(highBytes) + ByteUtils.toHexString(lowBytes)); + map.put(PRINT_COMMENT, ""); + return map; + } + public byte[] getHighBytes() { return highBytes; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java index c7b6fbe4ac..57b157dbe0 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java @@ -1,12 +1,16 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class MethodHandleInfo implements Constant { +public class MethodHandleInfo implements Constant, IReference { private int referenceKind; private int referenceIndex; @@ -20,6 +24,11 @@ public int size() { return 4; } + @Override + public Map printableMap() { + return null; + } + public int getReferenceKind() { return referenceKind; } @@ -27,4 +36,9 @@ public int getReferenceKind() { public int getReferenceIndex() { return referenceIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java index c52903956c..9af83bca59 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java @@ -1,14 +1,21 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class MethodRefInfo implements Constant { +public class MethodRefInfo implements Constant, IReference { private int classIndex; private int nameAndTypeIndex; + private String className; + private String nameAndType; public MethodRefInfo(int classIndex, int nameAndTypeIndex) { this.classIndex = classIndex; @@ -20,6 +27,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "MethodRef"); + map.put(PRINT_PARAM, "#" + classIndex + ".#" + nameAndTypeIndex); + map.put(PRINT_COMMENT, "// " + className + '.' + nameAndType); + return map; + } + public int getClassInfoIndex() { return classIndex; } @@ -27,4 +43,10 @@ public int getClassInfoIndex() { public int getNameAndTypeIndex() { return nameAndTypeIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + className = ((ClassInfo) constantPool.getConstantInfo(classIndex)).getClassName(); + nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java index 9b7e7cba1f..8377a48fe3 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java @@ -1,13 +1,19 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class MethodTypeInfo implements Constant { +public class MethodTypeInfo implements Constant, IReference { private int descriptorIndex; + private String descriptor; public MethodTypeInfo(int descriptorIndex) { this.descriptorIndex = descriptorIndex; @@ -18,7 +24,21 @@ public int size() { return 3; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "MethodType"); + map.put(PRINT_PARAM, "#" + descriptorIndex); + map.put(PRINT_COMMENT, "// " + descriptor); + return map; + } + public int getDescriptorIndex() { return descriptorIndex; } + + @Override + public void linkReference(ConstantPool constantPool) { + descriptor = ((UTF8Info) constantPool.getConstantInfo(descriptorIndex)).getValue(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java index c783b969e7..6ec20e6f3f 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java @@ -1,14 +1,21 @@ package jvm.classfile.constant.item.impl; +import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. * TODO: */ -public class NameAndTypeInfo implements Constant { +public class NameAndTypeInfo implements Constant, IReference { private int nameIndex; private int descriptorIndex; + private String name; + private String descriptor; public NameAndTypeInfo(int nameIndex, int descriptorIndex) { this.nameIndex = nameIndex; @@ -20,6 +27,15 @@ public int size() { return 5; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "NameAndType"); + map.put(PRINT_PARAM, "#" + nameIndex + ":#" + descriptorIndex); + map.put(PRINT_COMMENT, "// " + name + ':' + descriptor); + return map; + } + public int getNameIndex() { return nameIndex; } @@ -35,4 +51,14 @@ public int getIndex1() { public int getIndex2() { return descriptorIndex; } + + public String getNameAndType() { + return name + ':' + descriptor; + } + + @Override + public void linkReference(ConstantPool constantPool) { + name = ((UTF8Info) constantPool.getConstantInfo(nameIndex)).getValue(); + descriptor = ((UTF8Info) constantPool.getConstantInfo(descriptorIndex)).getValue(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java index 6e7548db05..58c4d6b517 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java @@ -4,6 +4,9 @@ import jvm.classfile.constant.item.Constant; import jvm.classfile.constant.item.IReference; +import java.util.HashMap; +import java.util.Map; + /** * Created by Haochen on 2017/4/9. * TODO: @@ -21,6 +24,15 @@ public int size() { return 3; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "String"); + map.put(PRINT_PARAM, "#" + stringIndex); + map.put(PRINT_COMMENT, "// " + value); + return map; + } + public String getValue() { return value; } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java index 86d139fb7c..490c07bf28 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java @@ -3,6 +3,8 @@ import jvm.classfile.constant.item.Constant; import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; /** * Created by Haochen on 2017/4/9. @@ -26,6 +28,14 @@ public int size() { return 3 + length; } + @Override + public Map printableMap() { + Map map = new HashMap<>(); + map.put(PRINT_TYPE, "Utf8"); + map.put(PRINT_PARAM, value); + return map; + } + public int getLength() { return length; } diff --git a/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java index 632f36c2ea..1d2ca39d46 100644 --- a/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java +++ b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java @@ -4,6 +4,9 @@ import jvm.classfile.ClassFile; import jvm.exception.ReadClassException; +import java.util.ArrayList; +import java.util.List; + public class ClassFilePrinter { ClassFile clzFile; diff --git a/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java b/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java index e528f351ad..4ab6b092f6 100644 --- a/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java +++ b/group01/895457260/code/src/main/java/jvm/print/ConstantPoolPrinter.java @@ -1,6 +1,12 @@ package jvm.print; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class ConstantPoolPrinter { ConstantPool pool; @@ -11,5 +17,43 @@ public class ConstantPoolPrinter { public void print() { System.out.println("Constant Pool:"); + final List> maps = new LinkedList<>(); + pool.forEach(c -> maps.add(c.printableMap())); + maps.remove(0); + + int[] maxLens = getMaxValueLengths(maps); + + String format = "%" + ((maps.size() + "").length() + 3) + + "s = %" + ((maxLens[0] + 8) > 0 ? "-" + (maxLens[0] + 8) : "") + + "s%" + ((maxLens[1] + 8) > 0 ? "-" + (maxLens[1] + 8) : "") + + "s%s\n"; + + for (int i = 0; i < maps.size(); ++i) { + Map m = maps.get(i); + String type = m.get(Constant.PRINT_TYPE); + String param = m.get(Constant.PRINT_PARAM); + String comment = m.get(Constant.PRINT_COMMENT); + System.out.printf(format, "#" + (i + 1), + type == null ? "" : type, + param == null ? "" : param, + comment == null ? "" : comment); + } + } + + private int[] getMaxValueLengths(List> maps) { + int maxLen[] = new int[2]; + for (Map m : maps) { + String type = m.get(Constant.PRINT_TYPE); + if (type != null && type.length() > maxLen[0]) { + maxLen[0] = type.length(); + } + if (type == null || !"utf8".equals(type.toLowerCase())) { + String param = m.get(Constant.PRINT_PARAM); + if (param != null && param.length() > maxLen[1]) { + maxLen[1] = param.length(); + } + } + } + return maxLen; } } From 91e46e68419f6473ab0b60a9cb5f70aef956bcf5 Mon Sep 17 00:00:00 2001 From: Haochen Date: Sat, 22 Apr 2017 08:32:04 +0800 Subject: [PATCH 096/151] finish InfixToPostfix --- .../algorithm/expression/InfixToPostfix.java | 32 ++++++++-- .../main/java/algorithm/expression/Token.java | 59 +++++++++++------ .../algorithm/expression/TokenParser.java | 7 ++- .../expression/InfixToPostfixTest.java | 63 +++++++++++++++++++ 4 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 group01/895457260/code/src/test/java/algorithm/expression/InfixToPostfixTest.java diff --git a/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java b/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java index 58ffe99cd3..44c6bbcd09 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/InfixToPostfix.java @@ -1,14 +1,34 @@ package algorithm.expression; +import datastructure.basic.Stack; + +import java.util.ArrayList; import java.util.List; public class InfixToPostfix { - public static List convert(String expr) { - - return null; - } - - + List infix = TokenParser.parse(expr); + List postfix = new ArrayList<>(); + Stack op = new Stack(); + for (Token token : infix) { + if (token.isNumber()) { + postfix.add(token); + } else if (token.equals(Token.R_BRACKET)) { + while (!op.peek().equals(Token.L_BRACKET)) { + postfix.add((Token) op.pop()); + } + op.pop(); + } else { + while (!op.isEmpty() && Token.compare(token, (Token) op.peek()) < 0) { + postfix.add((Token) op.pop()); + } + op.push(token); + } + } + while (!op.isEmpty()) { + postfix.add((Token) op.pop()); + } + return postfix; + } } diff --git a/group01/895457260/code/src/main/java/algorithm/expression/Token.java b/group01/895457260/code/src/main/java/algorithm/expression/Token.java index 3aa4f6f9c4..cb95b43f66 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/Token.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/Token.java @@ -1,22 +1,24 @@ package algorithm.expression; -import java.util.Arrays; -import java.util.List; - class Token { - public static final String ADD = "+"; - public static final String SUB = "-"; - public static final String MUL = "*"; - public static final String DIV = "/"; - public static final String L_BRACKET = "("; - public static final String R_BRACKET = ")"; - - public static final List OPERATORS = Arrays.asList(ADD, SUB, MUL, DIV, L_BRACKET, R_BRACKET); + public static final String OP_ADD = "+"; + public static final String OP_SUB = "-"; + public static final String OP_MUL = "*"; + public static final String OP_DIV = "/"; + public static final String OP_L_BRACKET = "("; + public static final String OP_R_BRACKET = ")"; + public static final String OP_SCOPE = "#"; + public static final int OPERATOR = 1; public static final int NUMBER = 2; - public static final String SCOPE_STR = "#"; - public static final Token SCOPE = new Token(OPERATOR, SCOPE_STR); + public static final Token ADD = new Token(OPERATOR, OP_ADD); + public static final Token SUB = new Token(OPERATOR, OP_SUB); + public static final Token MUL = new Token(OPERATOR, OP_MUL); + public static final Token DIV = new Token(OPERATOR, OP_DIV); + public static final Token L_BRACKET = new Token(OPERATOR, OP_L_BRACKET); + public static final Token R_BRACKET = new Token(OPERATOR, OP_R_BRACKET); + public static final Token SCOPE = new Token(OPERATOR, OP_SCOPE); //优先级表 private static int[][] priorities = { @@ -56,19 +58,19 @@ public String toString(){ private static int indexOf(String op) { switch (op) { - case ADD: + case OP_ADD: return 0; - case SUB: + case OP_SUB: return 1; - case MUL: + case OP_MUL: return 2; - case DIV: + case OP_DIV: return 3; - case L_BRACKET: + case OP_L_BRACKET: return 4; - case R_BRACKET: + case OP_R_BRACKET: return 5; - case SCOPE_STR: + case OP_SCOPE: return 6; } return 0; @@ -103,4 +105,21 @@ public static Token calculate(Token num1, Token op, Token num2) { } return new Token(NUMBER, result + ""); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Token token = (Token) o; + + return type == token.type && (value != null ? value.equals(token.value) : token.value == null); + } + + @Override + public int hashCode() { + int result = value != null ? value.hashCode() : 0; + result = 31 * result + type; + return result; + } } \ No newline at end of file diff --git a/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java index fc146579bd..ca8619c94b 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java @@ -1,9 +1,14 @@ package algorithm.expression; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class TokenParser { + public static final List OPERATORS = + Arrays.asList(Token.OP_ADD, Token.OP_SUB, Token.OP_MUL, + Token.OP_DIV, Token.OP_L_BRACKET, Token.OP_R_BRACKET); + public static List parse(String expression) { return parse(expression, null); } @@ -48,6 +53,6 @@ private static int indexOfNextOperator(int i, String expr) { private static boolean isOperator(char c) { String sc = String.valueOf(c); - return Token.OPERATORS.contains(sc); + return OPERATORS.contains(sc); } } diff --git a/group01/895457260/code/src/test/java/algorithm/expression/InfixToPostfixTest.java b/group01/895457260/code/src/test/java/algorithm/expression/InfixToPostfixTest.java new file mode 100644 index 0000000000..7ea5c86807 --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/expression/InfixToPostfixTest.java @@ -0,0 +1,63 @@ +package algorithm.expression; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +/** +* InfixToPostfix Tester. +* +* @author +* @since
四月 22, 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 expr = "2+3*4+5"; + Assert.assertEquals("[2, 3, 4, *, +, 5, +]", + InfixToPostfix.convert(expr).toString()); + } + + { + String expr = "3*20+12*5-40/2"; + Assert.assertEquals("[3, 20, *, 12, 5, *, +, 40, 2, /, -]", + InfixToPostfix.convert(expr).toString()); + } + + { + String expr = "3*20/2"; + Assert.assertEquals("[3, 20, *, 2, /]", + InfixToPostfix.convert(expr).toString()); + } + + { + String expr = "20/2*3"; + Assert.assertEquals("[20, 2, /, 3, *]", + InfixToPostfix.convert(expr).toString()); + } + + { + String expr = "10-30+50"; + Assert.assertEquals("[10, 30, -, 50, +]", + InfixToPostfix.convert(expr).toString()); + } +} + +} From 7a922e24be7eda17a5813edd42057386f68f9798 Mon Sep 17 00:00:00 2001 From: sdnb Date: Sat, 22 Apr 2017 12:52:32 +0800 Subject: [PATCH 097/151] =?UTF-8?q?=E4=B8=AD=E5=BA=8F=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/week6/exprNew/InfixExpr.java | 58 ++++++++++++++ .../com/coding/week6/exprNew/Operator.java | 75 ++++++++++++++++++ .../java/com/coding/week6/exprNew/Token.java | 48 +++++++++++ .../com/coding/week6/exprNew/TokenParser.java | 51 ++++++++++++ .../week6/exprNew/InfixExprTestTest.java | 79 +++++++++++++++++++ .../coding/week6/exprNew/TokenParserTest.java | 18 +++++ 6 files changed, 329 insertions(+) create mode 100644 group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java create mode 100644 group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java create mode 100644 group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java create mode 100644 group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java create mode 100644 group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java create mode 100644 group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java new file mode 100644 index 0000000000..41704db5db --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java @@ -0,0 +1,58 @@ +package com.coding.week6.exprNew; + +import com.coding.weak1.Stack; + +import java.util.List; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + + public float evaluate() { + + Stack operatorStack = new Stack(); + Stack numberStack = new Stack(); + fillStack(numberStack, operatorStack); + while (!operatorStack.isEmpty()) { + Operator symbol = (Operator) operatorStack.pop(); + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(symbol.apply(operTop2, operTop1)); + } + return (float)numberStack.pop(); + } + + public void fillStack(Stack numberStack, Stack operatorStack) { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + for (Token token : tokens) { + if (token.isNumber()) { + numberStack.push((float)token.getIntValue()); + continue; + } + if (token.isOperator()) { + Operator o = token.getOperator(); + if (operatorStack.isEmpty()) { + operatorStack.push(o); + }else { + Operator topO = (Operator)operatorStack.peek(); + if (o.hasHigherPriority(topO)) { + operatorStack.push(o); + } else { + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(topO.apply(operTop2, operTop1)); + operatorStack.pop(); + operatorStack.push(o); + } + } + } + + } + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java new file mode 100644 index 0000000000..b91c8158bf --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java @@ -0,0 +1,75 @@ +package com.coding.week6.exprNew; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public enum Operator { + ADD("+", 1) { + float apply(float x, float y){ + return x + y; + } + }, + + SUB("-", 1) { + @Override + float apply(float x, float y) { + return x - y; + } + }, + + MULT("*", 2) { + @Override + float apply(float x, float y) { + return x * y; + } + }, + + DIVI("/", 2) { + @Override + float apply(float x, float y) { + return x / y; + } + }; + private String symbol; + private int priority; + + Operator(String symbol, int priority) { + this.symbol = symbol; + this.priority = priority; + } + + public boolean hasHigherPriority(Operator o) { + return this.priority > o.priority; + } + + public String symbol() { + return symbol; + } + + public static List symbols() { + List symbos = new ArrayList<>(); + for (Operator o : Operator.values()) { + symbos.add(o.symbol); + } + return symbos; + } + + abstract float apply(float x, float y); + + private static final Map map = new HashMap(); + + static { + for (Operator o : Operator.values()) { + map.put(o.symbol, o); + } + } + + public static Map getOperatorMap() { + return map; + } +} diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java new file mode 100644 index 0000000000..d987ac47b4 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java @@ -0,0 +1,48 @@ +package com.coding.week6.exprNew; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public class Token { + + private int type; + private String value; + + static final int NUMBER = 1; + static final int OPERATOR = 2; + 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() { + if (isNumber()) + return Integer.valueOf(value); + else + throw new RuntimeException("not a number"); + } + + public String toString() { + return type+":"+value; + } + + + public Operator getOperator() { + if (isOperator()) { + return Operator.getOperatorMap().get(value); + } else { + throw new RuntimeException("not a operator"); + } + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java new file mode 100644 index 0000000000..ee90c39701 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java @@ -0,0 +1,51 @@ +package com.coding.week6.exprNew; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public class TokenParser { + + private static List operators = Operator.symbols(); + public List parse(String expr) { + List tokens = new ArrayList<>(); + int i = 0; + while (i < expr.length()) { + char c = expr.charAt(i); + Token token; + if (Character.isDigit(c)) { + int nextOperIndex = getNextOperIndex(i, expr); + String n = expr.substring(i, nextOperIndex); + token = new Token(Token.NUMBER, n); + tokens.add(token); + i = nextOperIndex; + } else if (isOperator(c)) { + token = new Token(Token.OPERATOR, c+""); + tokens.add(token); + i++; + } else { + throw new RuntimeException(c +" is not number or support operator"); + } + + } + return tokens; + } + + private int getNextOperIndex(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + } + + private boolean isOperator(char c) { + return operators.contains(String.valueOf(c)); + } + + +} diff --git a/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java b/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java new file mode 100644 index 0000000000..d8f4a5390f --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java @@ -0,0 +1,79 @@ +package ew; + + +import com.coding.week6.exprNew.InfixExpr; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class InfixExprTestTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3|"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + + +// @Test +// public void testFillStack() { +// InfixExpr expr = new InfixExpr("10-30+50"); +// expr.fillStack(); +// Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); +// Assert.assertEquals(expr.printOperatorStack(), "+"); +// expr = new InfixExpr("3*20+12*5-40/2"); +// expr.fillStack(); +// Assert.assertEquals(expr.printNumberStack(), "2.0,40.0,60.0,60.0"); +// Assert.assertEquals(expr.printOperatorStack(), "/,-,+"); +// expr = new InfixExpr("3*20/2"); +// expr.fillStack(); +// Assert.assertEquals(expr.printNumberStack(), "2.0,60.0"); +// Assert.assertEquals(expr.printOperatorStack(), "/"); +// expr = new InfixExpr("20/2*3"); +// expr.fillStack(); +// Assert.assertEquals(expr.printNumberStack(), "3.0,10.0"); +// Assert.assertEquals(expr.printOperatorStack(), "*"); +// expr = new InfixExpr("10-30+50"); +// expr.fillStack(); +// Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); +// Assert.assertEquals(expr.printOperatorStack(), "+"); +// } + + + +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java b/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java new file mode 100644 index 0000000000..c919f0084f --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java @@ -0,0 +1,18 @@ +package com.coding.week6.exprNew; + +import org.junit.Test; + +import java.util.List; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public class TokenParserTest { + + @Test + public void testParse() throws Exception { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse("3*20+12*5-40/2"); + System.out.println(tokens); + } +} \ No newline at end of file From 886625ee40ca61b57b9286d72bf7dd2cab46c187 Mon Sep 17 00:00:00 2001 From: maishihang <446031103@qq.com> Date: Sat, 22 Apr 2017 15:19:42 +0800 Subject: [PATCH 098/151] update jvm the 2 work update jvm the 2 work --- .../coderising/jvm/attr/AttributeInfo.java | 19 +++ .../src/com/coderising/jvm/attr/CodeAttr.java | 56 +++++++ .../coderising/jvm/attr/LineNumberTable.java | 42 +++++ .../jvm/attr/LocalVariableItem.java | 39 +++++ .../jvm/attr/LocalVariableTable.java | 28 ++++ .../coderising/jvm/attr/StackMapTable.java | 30 ++++ .../src/com/coderising/jvm/field/Field.java | 33 ++++ .../jvm/loader/ByteCodeIterator.java | 54 ++++++- .../jvm/loader/ClassFileLoader.java | 2 +- .../jvm/loader/ClassFileParser.java | 117 +++++++++++++- .../src/com/coderising/jvm/method/Method.java | 57 +++++++ .../jvm/test/ClassFileloaderTest.java | 9 +- .../datastructure/linklist/LRUPageFrame.java | 144 ------------------ 13 files changed, 475 insertions(+), 155 deletions(-) create mode 100644 group12/446031103/src/com/coderising/jvm/attr/AttributeInfo.java create mode 100644 group12/446031103/src/com/coderising/jvm/attr/CodeAttr.java create mode 100644 group12/446031103/src/com/coderising/jvm/attr/LineNumberTable.java create mode 100644 group12/446031103/src/com/coderising/jvm/attr/LocalVariableItem.java create mode 100644 group12/446031103/src/com/coderising/jvm/attr/LocalVariableTable.java create mode 100644 group12/446031103/src/com/coderising/jvm/attr/StackMapTable.java create mode 100644 group12/446031103/src/com/coderising/jvm/field/Field.java create mode 100644 group12/446031103/src/com/coderising/jvm/method/Method.java diff --git a/group12/446031103/src/com/coderising/jvm/attr/AttributeInfo.java b/group12/446031103/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group12/446031103/src/com/coderising/jvm/attr/CodeAttr.java b/group12/446031103/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..ee7d423c3b --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group12/446031103/src/com/coderising/jvm/attr/LineNumberTable.java b/group12/446031103/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..d88752e323 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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){ + + return null; + } + + + +} diff --git a/group12/446031103/src/com/coderising/jvm/attr/LocalVariableItem.java b/group12/446031103/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group12/446031103/src/com/coderising/jvm/attr/LocalVariableTable.java b/group12/446031103/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..e4d3df0e77 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + return null; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group12/446031103/src/com/coderising/jvm/attr/StackMapTable.java b/group12/446031103/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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/group12/446031103/src/com/coderising/jvm/field/Field.java b/group12/446031103/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..0d1c64587c --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + +} diff --git a/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java index 9c9fac2839..6fb5570dff 100644 --- a/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -1,5 +1,57 @@ package com.coderising.jvm.loader; -public class ByteCodeIterator { +import java.util.Arrays; +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } } diff --git a/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java b/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java index 33185d8175..070a0ba10b 100644 --- a/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -9,7 +9,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import com.coderising.jvm.clz.ClassFile; diff --git a/group12/446031103/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/446031103/src/com/coderising/jvm/loader/ClassFileParser.java index 8e29f14a0c..a30cb22ad1 100644 --- a/group12/446031103/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group12/446031103/src/com/coderising/jvm/loader/ClassFileParser.java @@ -13,32 +13,139 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFileParser { public ClassFile parse(byte[] codes) { - + ClassFile clzFile = new ClassFile(); + + ByteCodeIterator iter = new ByteCodeIterator(codes); + + String magicNumber = iter.nextU4ToHexString(); + + if (!"cafebabe".equals(magicNumber)) { + return null; + } + + clzFile.setMinorVersion(iter.nextU2ToInt()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); - return null; + ClassIndex clzIndex = parseClassInfex(iter); + clzFile.setClassIndex(clzIndex); + + parseInterfaces(iter); + + + return clzFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { - return null; + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + // System.out.println("Is public class: " + flag.isPublicClass()); + // System.out.println("Is final class : " + flag.isFinalClass()); + + return flag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { - return null; + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + + return clzIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { - return null; + int constPoolCount = iter.nextU2ToInt(); + + System.out.println("Constant Pool Count :" + constPoolCount); + + ConstantPool pool = new ConstantPool(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= constPoolCount - 1; i++) { + + int tag = iter.nextU1toInt(); + + if (tag == 7) { + // Class Info + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + + pool.addConstantInfo(clzInfo); + } else if (tag == 1) { + // UTF-8 String + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + }else if (tag == 8) { + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == 9) { + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == 10) { + // MethodRef + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == 12) { + // Name and Type Info + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setIndex1(iter.nextU2ToInt()); + nameType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); + } + } + + System.out.println("Finished reading Constant pool "); + + return pool; + } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 } + } diff --git a/group12/446031103/src/com/coderising/jvm/method/Method.java b/group12/446031103/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..b57ef592d2 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + return null; + + } +} diff --git a/group12/446031103/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group12/446031103/src/com/coderising/jvm/test/ClassFileloaderTest.java index 26407abbef..a0cbf7a626 100644 --- a/group12/446031103/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group12/446031103/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -23,15 +23,16 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; - static String path2 = "C:\temp"; + //模拟windows中的path,path用;连接,要在这串path中寻找jvm + //static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path1 = "E:\\mygit\\coding2017\\group12\\446031103\\bin"; + static String path2 = "E:\temp"; static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; - + String className = "com.coderising.jvm.test.EmployeeV1"; clzFile = loader.loadClass(className); clzFile.print(); } diff --git a/group12/446031103/src/com/datastructure/linklist/LRUPageFrame.java b/group12/446031103/src/com/datastructure/linklist/LRUPageFrame.java index cdb42d1fdd..00be77f3d0 100644 --- a/group12/446031103/src/com/datastructure/linklist/LRUPageFrame.java +++ b/group12/446031103/src/com/datastructure/linklist/LRUPageFrame.java @@ -165,150 +165,6 @@ public String toString(){ return buffer.toString(); } - /*private static class Node { - - Node prev; - Node next; - int pageNum; - - Node(Node prev,Node next,int pageNum) { - this.prev = prev; - this.next = next; - this.pageNum = pageNum; - } - Node(){ - - } - } - - private int capacity; - private int addCnt ; - private int size; - private Node first;// 链表头 - private Node last;// 链表尾 - - - public LRUPageFrame(int capacity) { - - this.capacity = capacity; - first = new Node(); - } - - *//** - * 获取缓存中对象 - * - * @param key - * @return - *//* - public void access(int pageNum) { - if(null==this.last){ - this.last = new Node(this.first,null,pageNum); - this.first.next = this.last; - addCnt++; - size++; - return; - } - if(contain(pageNum)){ - if(Objects.equals(this.first.next.pageNum, pageNum)){ - return; - } - boolean temp = Objects.equals(getLastNode(size).pageNum, pageNum); - Node currentNode = getNode(pageNum); - Node nextNode = currentNode.next; - Node preNode = currentNode.prev; - - currentNode.prev = this.first; - currentNode.next = this.first.next; - this.first.next = currentNode; - - if(temp){ - preNode.next = null; - if(null==preNode.prev) - preNode.prev = currentNode; - }else{ - preNode.prev = currentNode; - preNode.next = nextNode; - nextNode.next = null; - nextNode.prev = preNode; - } - this.last = getLastNode(size); - return; - } - Node addNode = new Node(this.first,this.first.next,pageNum); - Node oldFirstnode=this.first.next ; - oldFirstnode.prev = addNode; - this.first.next = addNode; - if(isOut()){ - - addCnt++; - if(this.size !=this.capacity ) - size++; - if(addCnt>size) - this.last.prev.next = null; - this.last = getLastNode(size); - }else{ - this.last.prev.next = null; - } - - - } - private boolean isOut(){ - return this.addCnt<=this.capacity; - } - - private Node getLastNode(int sizes) { - Node node=this.first; - for (int i = 0; i < sizes; i++) { - node = node.next; - } - return node; - } - - private boolean contain(Object o){ - Node node = this.first; - - while(null!=node.next){ - - node = node.next; - - if(Objects.equals(node.pageNum,o)){ - return true; - } - - } - return false; - } - - private Node getNode(Object o){ - Node node = this.first; - - while(null!=node.next){ - - node = node.next; - - if(Objects.equals(node.pageNum,o)){ - return node; - } - - } - return null; - } - - - - - public String toString(){ - StringBuilder buffer = new StringBuilder(); - Node node = first; - while(node.next != null){ - node = node.next; - buffer.append(node.pageNum); - if(node.next != null){ - buffer.append(","); - } - } - return buffer.toString(); - }*/ } \ No newline at end of file From cd642e815266556102bb483cc18c98f23ebc9748 Mon Sep 17 00:00:00 2001 From: gongxun Date: Sat, 22 Apr 2017 15:40:55 +0800 Subject: [PATCH 099/151] =?UTF-8?q?=E5=AE=8C=E6=88=90javap=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4.16/print/ClassFilePrinter.java | 8 +- .../4.16/print/ConstantPoolPrinter.java | 82 +++++++++++++++++-- group17/785396327/4.5/constant/ClassInfo.java | 2 +- .../785396327/4.5/constant/FieldRefInfo.java | 2 +- .../4.5/constant/NameAndTypeInfo.java | 2 +- .../4.5/constant/NullConstantInfo.java | 2 +- group17/785396327/4.5/constant/UTF8Info.java | 2 +- .../785396327/4.9/expr/InfixToPostfix.java | 13 +++ group17/785396327/4.9/expr/PostfixExpr.java | 16 ++++ .../785396327/4.9/expr/PostfixExprTest.java | 38 +++++++++ group17/785396327/4.9/expr/PrefixExpr.java | 16 ++++ .../785396327/4.9/expr/PrefixExprTest.java | 45 ++++++++++ group17/785396327/4.9/expr/Token.java | 52 ++++++++++++ group17/785396327/4.9/expr/TokenParser.java | 58 +++++++++++++ .../785396327/4.9/expr/TokenParserTest.java | 40 +++++++++ 15 files changed, 359 insertions(+), 19 deletions(-) create mode 100644 group17/785396327/4.9/expr/InfixToPostfix.java create mode 100644 group17/785396327/4.9/expr/PostfixExpr.java create mode 100644 group17/785396327/4.9/expr/PostfixExprTest.java create mode 100644 group17/785396327/4.9/expr/PrefixExpr.java create mode 100644 group17/785396327/4.9/expr/PrefixExprTest.java create mode 100644 group17/785396327/4.9/expr/Token.java create mode 100644 group17/785396327/4.9/expr/TokenParser.java create mode 100644 group17/785396327/4.9/expr/TokenParserTest.java diff --git a/group17/785396327/4.16/print/ClassFilePrinter.java b/group17/785396327/4.16/print/ClassFilePrinter.java index 2c2b49bab0..7d8c878553 100644 --- a/group17/785396327/4.16/print/ClassFilePrinter.java +++ b/group17/785396327/4.16/print/ClassFilePrinter.java @@ -27,17 +27,13 @@ public void print(){ 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"; + String path = "G:\\Git\\homework\\coding2017\\group17\\785396327\\out\\production\\785396327"; ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "jvm_1.EmployeeV1"; ClassFile clzFile = loader.loadClass(className); diff --git a/group17/785396327/4.16/print/ConstantPoolPrinter.java b/group17/785396327/4.16/print/ConstantPoolPrinter.java index 9e17cc1ff2..6c4d4fee4a 100644 --- a/group17/785396327/4.16/print/ConstantPoolPrinter.java +++ b/group17/785396327/4.16/print/ConstantPoolPrinter.java @@ -7,42 +7,108 @@ */ public class ConstantPoolPrinter { ConstantPool pool; - ConstantPoolPrinter(ConstantPool pool){ + + ConstantPoolPrinter(ConstantPool pool) { this.pool = pool; } - public void print(){ + + public void print() { System.out.println("Constant Pool:"); ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { @Override public void visitClassInfo(ClassInfo info) { - + // #7 = Class #44 // jvm_1/EmployeeV1 + StringBuilder sb = new StringBuilder(); + sb.append("Class") + .append("\t\t\t") + .append("#" + info.getUtf8Index()) + .append("\t\t\t\t") + .append("//\t") + .append(info.getClassName()); + System.out.println(sb.toString()); } @Override public void visitFieldRef(FieldRefInfo info) { - + // #2 = Fieldref #7.#37 // jvm_1/EmployeeV1.name:Ljava/lang/String; + StringBuilder sb = new StringBuilder(); + sb.append("Fieldref") + .append("\t\t") + .append("#" + info.getClassInfoIndex()) + .append(".") + .append("#" + info.getNameAndTypeIndex()) + .append("\t\t\t") + .append("//\t") + .append(info.getClassName()) + .append(".") + .append(info.getFieldName()) + .append(info.getFieldType()); + System.out.println(sb.toString()); } @Override public void visitMethodRef(MethodRefInfo info) { - + // #1 = Methodref #11.#36 // java/lang/Object."":()V + StringBuilder sb = new StringBuilder(); + sb.append("Methodref") + .append("\t\t") + .append("#" + info.getClassInfoIndex()) + .append(".") + .append("#" + info.getNameAndTypeIndex()) + .append("\t\t\t") + .append("//\t") + .append(info.getClassName()) + .append(".") + .append(info.getMethodName()); + System.out.println(sb.toString()); } @Override public void visitNameAndType(NameAndTypeInfo info) { - + // #36 = NameAndType #16:#28 // "":()V + StringBuilder sb = new StringBuilder(); + sb.append("NameAndType") + .append("\t\t") + .append("#" + info.getIndex1()) + .append(":") + .append("#" + info.getIndex2()) + .append("\t\t\t") + .append("//\t") + .append(info.getTypeInfo()) + .append(":") + .append(info.getName()); + System.out.println(sb.toString()); } @Override public void visitString(StringInfo info) { - + // #5 = String #41 // Hello , this is class Employee + StringBuilder sb = new StringBuilder(); + sb.append("String") + .append("\t\t\t") + .append("#" + info.getIndex()) + .append("\t\t\t\t") + .append("//\t") + .append(((UTF8Info) info.getConstantInfo(info.getIndex())).getValue()); + System.out.println(sb.toString()); } @Override public void visistUTF8(UTF8Info info) { - + // #32 = Utf8 [Ljava/lang/String; + StringBuilder sb = new StringBuilder(); + sb.append("Utf8") + .append("\t\t\t") + .append(info.getValue()); + System.out.println(sb.toString()); } }; + + for (int i = 1; i < (Integer) pool.getSize(); i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#" + i + "\t=\t"); + constantInfo.accept(visitor); + } } } diff --git a/group17/785396327/4.5/constant/ClassInfo.java b/group17/785396327/4.5/constant/ClassInfo.java index 4bc1f373df..02aa4b2699 100644 --- a/group17/785396327/4.5/constant/ClassInfo.java +++ b/group17/785396327/4.5/constant/ClassInfo.java @@ -21,7 +21,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + visitor.visitClassInfo(this); } public String getClassName() { diff --git a/group17/785396327/4.5/constant/FieldRefInfo.java b/group17/785396327/4.5/constant/FieldRefInfo.java index 7d813221f5..2f3d2ee351 100644 --- a/group17/785396327/4.5/constant/FieldRefInfo.java +++ b/group17/785396327/4.5/constant/FieldRefInfo.java @@ -17,7 +17,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + visitor.visitFieldRef(this); } public int getClassInfoIndex() { diff --git a/group17/785396327/4.5/constant/NameAndTypeInfo.java b/group17/785396327/4.5/constant/NameAndTypeInfo.java index a65456d245..c7e720c0e3 100644 --- a/group17/785396327/4.5/constant/NameAndTypeInfo.java +++ b/group17/785396327/4.5/constant/NameAndTypeInfo.java @@ -34,7 +34,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + visitor.visitNameAndType(this); } diff --git a/group17/785396327/4.5/constant/NullConstantInfo.java b/group17/785396327/4.5/constant/NullConstantInfo.java index f3b1201e3a..c49d937c76 100644 --- a/group17/785396327/4.5/constant/NullConstantInfo.java +++ b/group17/785396327/4.5/constant/NullConstantInfo.java @@ -14,7 +14,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + System.out.println("null Constant info"); } } diff --git a/group17/785396327/4.5/constant/UTF8Info.java b/group17/785396327/4.5/constant/UTF8Info.java index 8cf71cc4dc..814615f4f2 100644 --- a/group17/785396327/4.5/constant/UTF8Info.java +++ b/group17/785396327/4.5/constant/UTF8Info.java @@ -22,7 +22,7 @@ public int getType() { @Override public void accept(Visitor visitor) { - + visitor.visistUTF8(this); } @Override diff --git a/group17/785396327/4.9/expr/InfixToPostfix.java b/group17/785396327/4.9/expr/InfixToPostfix.java new file mode 100644 index 0000000000..720be5b28a --- /dev/null +++ b/group17/785396327/4.9/expr/InfixToPostfix.java @@ -0,0 +1,13 @@ +package expr; + +import java.util.List; + +/** + * Created by gongxun on 2017/4/22. + */ +public class InfixToPostfix { + public static List convert(String expr) { + + return null; + } +} diff --git a/group17/785396327/4.9/expr/PostfixExpr.java b/group17/785396327/4.9/expr/PostfixExpr.java new file mode 100644 index 0000000000..a6d19be939 --- /dev/null +++ b/group17/785396327/4.9/expr/PostfixExpr.java @@ -0,0 +1,16 @@ +package expr; + +/** + * Created by gongxun on 2017/4/22. + */ +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } +} diff --git a/group17/785396327/4.9/expr/PostfixExprTest.java b/group17/785396327/4.9/expr/PostfixExprTest.java new file mode 100644 index 0000000000..378e8f2407 --- /dev/null +++ b/group17/785396327/4.9/expr/PostfixExprTest.java @@ -0,0 +1,38 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/22. + */ +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/group17/785396327/4.9/expr/PrefixExpr.java b/group17/785396327/4.9/expr/PrefixExpr.java new file mode 100644 index 0000000000..e86d6463c0 --- /dev/null +++ b/group17/785396327/4.9/expr/PrefixExpr.java @@ -0,0 +1,16 @@ +package expr; + +/** + * Created by gongxun on 2017/4/22. + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } +} diff --git a/group17/785396327/4.9/expr/PrefixExprTest.java b/group17/785396327/4.9/expr/PrefixExprTest.java new file mode 100644 index 0000000000..c2574eb155 --- /dev/null +++ b/group17/785396327/4.9/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/22. + */ +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/group17/785396327/4.9/expr/Token.java b/group17/785396327/4.9/expr/Token.java new file mode 100644 index 0000000000..093be5c416 --- /dev/null +++ b/group17/785396327/4.9/expr/Token.java @@ -0,0 +1,52 @@ +package expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by gongxun on 2017/4/22. + */ +public 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 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; + } + + +} diff --git a/group17/785396327/4.9/expr/TokenParser.java b/group17/785396327/4.9/expr/TokenParser.java new file mode 100644 index 0000000000..5620ad9f50 --- /dev/null +++ b/group17/785396327/4.9/expr/TokenParser.java @@ -0,0 +1,58 @@ +package expr; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by gongxun on 2017/4/22. + */ +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/group17/785396327/4.9/expr/TokenParserTest.java b/group17/785396327/4.9/expr/TokenParserTest.java new file mode 100644 index 0000000000..22fe16dc85 --- /dev/null +++ b/group17/785396327/4.9/expr/TokenParserTest.java @@ -0,0 +1,40 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +/** + * Created by gongxun on 2017/4/22. + */ +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()); + } +} From 64c602aa31f363f7af3db2b97059540cde63a8dd Mon Sep 17 00:00:00 2001 From: xukai Date: Sat, 22 Apr 2017 15:53:05 +0800 Subject: [PATCH 100/151] =?UTF-8?q?jvm=E7=AC=AC=E5=9B=9B=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/xukai/coderising/stack/InfixExpr.java | 173 ++++++------------ .../xukai/coderising/stack/InfixExpr2.java | 104 +++++++++++ .../coderising/stack/InfixToPostfix2.java | 87 +++++++++ .../xukai/coderising/stack/PostfixExpr.java | 57 ++++++ .../coderising/stack/PostfixExprTest.java | 47 +++++ .../xukai/coderising/stack/PrefixExpr.java | 60 ++++++ .../coderising/stack/PrefixExprTest.java | 45 +++++ .../org/xukai/coderising/stack/Token.java | 50 +++++ .../xukai/coderising/stack/TokenParser.java | 57 ++++++ .../java/org/xukai/jvm/attr/CodeAttr.java | 21 ++- .../java/org/xukai/jvm/clz/ClassFile.java | 32 +++- .../java/org/xukai/jvm/cmd/BiPushCmd.java | 22 +++ .../org/xukai/jvm/cmd/ByteCodeCommand.java | 129 +++++++++++++ .../java/org/xukai/jvm/cmd/CommandParser.java | 156 ++++++++++++++++ .../java/org/xukai/jvm/cmd/GetFieldCmd.java | 22 +++ .../org/xukai/jvm/cmd/GetStaticFieldCmd.java | 20 ++ .../org/xukai/jvm/cmd/InvokeSpecialCmd.java | 22 +++ .../org/xukai/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../main/java/org/xukai/jvm/cmd/LdcCmd.java | 30 +++ .../java/org/xukai/jvm/cmd/NewObjectCmd.java | 20 ++ .../java/org/xukai/jvm/cmd/NoOperandCmd.java | 24 +++ .../java/org/xukai/jvm/cmd/OneOperandCmd.java | 28 +++ .../java/org/xukai/jvm/cmd/PutFieldCmd.java | 20 ++ .../java/org/xukai/jvm/cmd/TwoOperandCmd.java | 67 +++++++ .../org/xukai/jvm/constant/ClassInfo.java | 7 +- .../org/xukai/jvm/constant/ConstantInfo.java | 19 ++ .../org/xukai/jvm/constant/ConstantPool.java | 2 +- .../org/xukai/jvm/constant/FieldRefInfo.java | 7 +- .../org/xukai/jvm/constant/MethodRefInfo.java | 7 +- .../xukai/jvm/constant/NameAndTypeInfo.java | 9 +- .../xukai/jvm/constant/NullConstantInfo.java | 7 +- .../org/xukai/jvm/constant/StringInfo.java | 7 +- .../java/org/xukai/jvm/constant/UTF8Info.java | 6 + .../java/org/xukai/jvm/method/Method.java | 13 +- .../org/xukai/jvm/print/ClassFilePrinter.java | 48 +++++ .../xukai/jvm/print/ConstantPoolPrinter.java | 85 +++++++++ .../xukai/jvm/test/ClassFileloaderTest.java | 83 ++++++++- 37 files changed, 1470 insertions(+), 145 deletions(-) create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr2.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixToPostfix2.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExpr.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExprTest.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExpr.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExprTest.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Token.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TokenParser.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/CommandParser.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/OneOperandCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ClassFilePrinter.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ConstantPoolPrinter.java diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java index bec5202645..b285a214b8 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java @@ -1,137 +1,76 @@ package org.xukai.coderising.stack; -import com.google.common.collect.Maps; -import com.sun.org.apache.bcel.internal.generic.IFNE; +import java.util.List; +import java.util.Stack; -import java.util.HashMap; public class InfixExpr { - - public static enum TypeToken { - - add('+',0),substruct('-',1),devide('/',3),plus('*',2); - - TypeToken(char token, Integer priority) { - this.token = token; - this.priority = priority; - } - - private char token; - - private Integer priority; - } - String expr = null; public InfixExpr(String expr) { this.expr = expr; } -//3*20+12*5-40/2 - public Double evaluate() { - HashMap map = new HashMap<>(); - map.put("+",0); - map.put("-",1); - map.put("/",3); - map.put("*",2); - - - Stack tokenStack = new Stack(); - Stack numStack = new Stack(); - char[] chars = expr.toCharArray(); - boolean isNem = true; - for (int i = 0; i < expr.length(); i++) { -// if (expr.charAt(i) == TypeToken.add.token || expr.charAt(i) == TypeToken.substruct.token) { -// isNem = true; -// if (!tokenStack.isEmpty() && (char)tokenStack.pop() == '*') { -// Float num2 = Float.valueOf(numStack.pop().toString()); -// Float num1 = Float.valueOf(numStack.pop().toString()); -// numStack.push(num1*num2); -// } else if (!tokenStack.isEmpty() && ((char)tokenStack.pop()) == '/') { -// Float num2 = Float.valueOf(numStack.pop().toString()); -// Float num1 = Float.valueOf(numStack.pop().toString()); -// numStack.push(num1/num2); -// } -// tokenStack.push(expr.charAt(i)); -// } else if (expr.charAt(i) == TypeToken.devide.token){ -// isNem = true; -// tokenStack.push(expr.charAt(i)); -// } else if (expr.charAt(i) == TypeToken.plus.token){ -// isNem = true; -// tokenStack.push(expr.charAt(i)); -// } else if (String.valueOf(expr.charAt(i)).matches("\\d{1}")){ -// if (isNem) { -// numStack.push((expr.charAt(i))); -// } else { -// numStack.push(numStack.pop().toString() + (expr.charAt(i))); -// } -// isNem = false; -// -// } else { -// throw new RuntimeException(); -// } - String token = (expr.charAt(i)) + ""; - Integer priprity = map.get(token); - if (priprity != null) { - //表示是运算符 - if (!tokenStack.isEmpty() && priprity < map.get(tokenStack.peek())) { - Float num2 = Float.valueOf(numStack.pop().toString()); - Float num1 = Float.valueOf(numStack.pop().toString()); - String pop = tokenStack.pop()+""; - if (pop.equals("-")) { - numStack.push(num1 - num2); - } else if (pop.equals("*")){ - numStack.push(num1 * num2); - } else if (pop.equals("/")){ - numStack.push(num1 / num2); - } else { - throw new RuntimeException(); + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + if(opStack.isEmpty()){ + + opStack.push(token); + } else{ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + } - - } - tokenStack.push(token); - isNem = true; - } else if(token.matches("\\d{1}")) { - //表示是数字 - if (isNem) { - numStack.push(token); - } else { - numStack.push(numStack.pop().toString() + token); + opStack.push(token); } - isNem = false; - } else { - throw new RuntimeException(); + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); } } - while (!tokenStack.isEmpty()) { - System.out.println(tokenStack.size()); - if (tokenStack.peek().equals("+")) { - Float num2 = Float.valueOf(numStack.pop().toString()); - Float num1 = Float.valueOf(numStack.pop().toString()); - numStack.push(num1+num2+""); - } else if (tokenStack.peek().equals("-")) { - Float num2 = Float.valueOf(numStack.pop().toString()); - Float num1 = Float.valueOf(numStack.pop().toString()); - numStack.push(num1-num2+""); - } else if (tokenStack.peek().equals("/")) { - Float num2 = Float.valueOf(numStack.pop().toString()); - Float num1 = Float.valueOf(numStack.pop().toString()); - numStack.push(num1/num2+""); - } else if (tokenStack.peek().equals("*")) { - Float num2 = Float.valueOf(numStack.pop().toString()); - Float num1 = Float.valueOf(numStack.pop().toString()); - numStack.push(num1*num2+""); - } else { - throw new RuntimeException(); - } - tokenStack.pop(); + + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); } -// System.out.println(Double.valueOf(numStack.pop().toString())); - return Double.valueOf(numStack.pop().toString()); + + + return numStack.pop().floatValue(); } - - public static void main(String[] args) { - + 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"); } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr2.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr2.java new file mode 100644 index 0000000000..00302fa05c --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr2.java @@ -0,0 +1,104 @@ +package org.xukai.coderising.stack; + +import java.util.HashMap; + +public class InfixExpr2 { + + public static enum TypeToken { + + add('+',0),substruct('-',1),devide('/',3),plus('*',2); + + TypeToken(char token, Integer priority) { + this.token = token; + this.priority = priority; + } + + private char token; + + private Integer priority; + } + + String expr = null; + + public InfixExpr2(String expr) { + this.expr = expr; + } +//3*20+12*5-40/2 + public Double evaluate() { + HashMap map = new HashMap<>(); + map.put("+",0); + map.put("-",1); + map.put("/",3); + map.put("*",2); + + + Stack tokenStack = new Stack(); + Stack numStack = new Stack(); + char[] chars = expr.toCharArray(); + boolean isNem = true; + for (int i = 0; i < expr.length(); i++) { + String token = (expr.charAt(i)) + ""; + Integer priprity = map.get(token); + if (priprity != null) { + //表示是运算符 + if (!tokenStack.isEmpty() && priprity < map.get(tokenStack.peek())) { + Float num2 = Float.valueOf(numStack.pop().toString()); + Float num1 = Float.valueOf(numStack.pop().toString()); + String pop = tokenStack.pop()+""; + if (pop.equals("-")) { + numStack.push(num1 - num2); + } else if (pop.equals("*")){ + numStack.push(num1 * num2); + } else if (pop.equals("/")){ + numStack.push(num1 / num2); + } else { + throw new RuntimeException(); + } + + } + tokenStack.push(token); + isNem = true; + } else if(token.matches("\\d{1}")) { + //表示是数字 + if (isNem) { + numStack.push(token); + } else { + numStack.push(numStack.pop().toString() + token); + } + isNem = false; + } else { + throw new RuntimeException(); + } + } + while (!tokenStack.isEmpty()) { + System.out.println(tokenStack.size()); + if (tokenStack.peek().equals("+")) { + Float num2 = Float.valueOf(numStack.pop().toString()); + Float num1 = Float.valueOf(numStack.pop().toString()); + numStack.push(num1+num2+""); + } else if (tokenStack.peek().equals("-")) { + Float num2 = Float.valueOf(numStack.pop().toString()); + Float num1 = Float.valueOf(numStack.pop().toString()); + numStack.push(num1-num2+""); + } else if (tokenStack.peek().equals("/")) { + Float num2 = Float.valueOf(numStack.pop().toString()); + Float num1 = Float.valueOf(numStack.pop().toString()); + numStack.push(num1/num2+""); + } else if (tokenStack.peek().equals("*")) { + Float num2 = Float.valueOf(numStack.pop().toString()); + Float num1 = Float.valueOf(numStack.pop().toString()); + numStack.push(num1*num2+""); + } else { + throw new RuntimeException(); + } + tokenStack.pop(); + } +// System.out.println(Double.valueOf(numStack.pop().toString())); + return Double.valueOf(numStack.pop().toString()); + } + + + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixToPostfix2.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixToPostfix2.java new file mode 100644 index 0000000000..71a483b29f --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixToPostfix2.java @@ -0,0 +1,87 @@ +package org.xukai.coderising.stack; + +import java.util.List; +import java.util.Stack; + +/** + * 将中缀表达式转换为后缀表达式: + 与转换为前缀表达式相似,遵循以下步骤: + (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2; + (2) 从左至右扫描中缀表达式; + (3) 遇到操作数时,将其压入S2; + (4) 遇到运算符时,比较其与S1栈顶运算符的优先级: + (4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈; + (4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况); + (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; + (5) 遇到括号时: + (5-1) 如果是左括号“(”,则直接压入S1; + (5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃; + (6) 重复步骤(2)至(5),直到表达式的最右边; + (7) 将S1中剩余的运算符依次弹出并压入S2; + (8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。 + + 例如,将中缀表达式“1+((2+3)×4)-5”转换为后缀表达式的过程如下: + 扫描到的元素 S2(栈底->栈顶) S1 (栈底->栈顶) 说明 + 1 1 空 数字,直接入栈 + + 1 + S1为空,运算符直接入栈 + ( 1 + ( 左括号,直接入栈 + ( 1 + ( ( 同上 + 2 1 2 + ( ( 数字 + + 1 2 + ( ( + S1栈顶为左括号,运算符直接入栈 + 3 1 2 3 + ( ( + 数字 + ) 1 2 3 + + ( 右括号,弹出运算符直至遇到左括号 + × 1 2 3 + + ( × S1栈顶为左括号,运算符直接入栈 + 4 1 2 3 + 4 + ( × 数字 + ) 1 2 3 + 4 × + 右括号,弹出运算符直至遇到左括号 + - 1 2 3 + 4 × + - -与+优先级相同,因此弹出+,再压入- + 5 1 2 3 + 4 × + 5 - 数字 + 到达最右端 1 2 3 + 4 × + 5 - 空 S1中剩余的运算符 + 因此结果为“1 2 3 + 4 × + 5 -”(注意需要逆序输出)。 + * @author xukai + * @desc + * @date 2017-04-22-14:10 + */ +public class InfixToPostfix2 { + + + private static TokenParser tokenParser = new TokenParser(); + + public static String toPostFixExpr(String expr){ + + List tokens = tokenParser.parse(expr); + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + for (Token token : tokens) { + if (token.isNumber()) { + s2.push(token); + } else { + while (token.isOperator() && !s1.isEmpty()) { + if (!token.hasHigherPriority(s1.peek())) { + s2.push(s1.pop()); + continue; + } + break; + } + s1.push(token); + } + } + while (!s1.isEmpty()) { + s2.push(s1.pop()); + } + StringBuilder stringBuilder = new StringBuilder(); + while (!s2.isEmpty()) { + Token token = s2.pop(); + s1.push(token); + } + while (!s1.isEmpty()) { + Token token = s1.pop(); + stringBuilder.append(token.toString()).append(" "); + } + + return stringBuilder.substring(0,stringBuilder.length() - 1); + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExpr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExpr.java new file mode 100644 index 0000000000..98e849c4ff --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExpr.java @@ -0,0 +1,57 @@ +package org.xukai.coderising.stack; + +import java.util.List; +import java.util.Stack; + +/** + * 与前缀表达式类似,只是顺序是从左至右: + 从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。 + 例如后缀表达式“3 4 + 5 × 6 -”: + (1) 从左至右扫描,将3和4压入堆栈; + (2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈; + (3) 将5入栈; + (4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈; + (5) 将6入栈; + (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 + */ +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + 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"); + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExprTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExprTest.java new file mode 100644 index 0000000000..178fc23836 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PostfixExprTest.java @@ -0,0 +1,47 @@ +package org.xukai.coderising.stack; + + + +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); + } + } + + @Test + public void testTo(){ + String poseExpr = InfixToPostfix2.toPostFixExpr("10-2*3+50"); + System.out.println(poseExpr); + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExpr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExpr.java new file mode 100644 index 0000000000..cab9831ec2 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExpr.java @@ -0,0 +1,60 @@ +package org.xukai.coderising.stack; + +import java.util.List; +import java.util.Stack; + +/** + * 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。 + 例如前缀表达式“- × + 3 4 5 6”: + (1) 从右至左扫描,将6、5、4、3压入堆栈; + (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈; + (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈; + (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 + 可以看出,用计算机计算前缀表达式的值是很容易的。 + * @author xukai + * @desc + * @date 2017-04-22-13:49 + */ +public class PrefixExpr { + + + private String expr; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate(){ + + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + + Stack numStack = new Stack(); + Stack oprStack = new Stack(); + + for (int i = tokens.size() - 1; i > -1; i--) { + if (tokens.get(i).isNumber()) { + numStack.push(new Float(tokens.get(i).getIntValue())); + } else { + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + numStack.push(caculate(tokens.get(i).toString(), num1, num2)); + } + } + + return numStack.pop(); + } + + private Float caculate(String oper, Float num1, Float num2){ + if (oper.equals("+")) { + return num1 + num2; + } else if (oper.equals("-")) { + return num1 - num2; + } else if (oper.equals("/")) { + return num1 / num2; + } else if (oper.equals("*")) { + return num1 * num2; + } + throw new RuntimeException("illeagal operation token"); + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExprTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExprTest.java new file mode 100644 index 0000000000..bc0e4b53e4 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/PrefixExprTest.java @@ -0,0 +1,45 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Token.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Token.java new file mode 100644 index 0000000000..e10eabb1f4 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Token.java @@ -0,0 +1,50 @@ +package org.xukai.coderising.stack; + +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 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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TokenParser.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TokenParser.java new file mode 100644 index 0000000000..03e214bf1b --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TokenParser.java @@ -0,0 +1,57 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java index d0c8ef4e32..fb08ebc8e2 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java @@ -2,6 +2,8 @@ import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.cmd.ByteCodeCommand; +import org.xukai.jvm.cmd.CommandParser; import org.xukai.jvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo { @@ -16,21 +18,23 @@ 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) { @@ -48,15 +52,14 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int maxLocals = iter.nextToInt(2); int codeLength = iter.nextToInt(4); String code = iter.nextToString(codeLength); - System.out.println(code); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, cmds); int exceptionTableLength = iter.nextToInt(2); if (exceptionTableLength > 0) { iter.nextToInt(exceptionTableLength); System.out.println("解析exception"); } int subAttributeCount = iter.nextToInt(2); - System.out.println("subAttributeCount" + subAttributeCount); if (subAttributeCount > 0) { for (int i = 0; i < subAttributeCount; i++) { AttributeInfo attributeInfo = AttributeInfo.parseAttribute(iter, clzFile); diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java index a2b2dfb515..c8777fea97 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java @@ -81,13 +81,41 @@ public void print(){ } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.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(); } + + 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(){ + 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; + } } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..bd1eb4bf11 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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(); + } + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..edb68e1256 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,129 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.ConstantInfo; +import org.xukai.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + + +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); +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/CommandParser.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..e44fb1e05f --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/CommandParser.java @@ -0,0 +1,156 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; + +import java.util.ArrayList; +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) { + + 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"); + } + + } + + calcuateOffset(cmds); + + 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; + } + + 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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..faa268b0d2 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..4112f7cc56 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..7dd0b62407 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..77ba5c7460 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..2d8b1ae2f3 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.ConstantInfo; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..0ac1b33832 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,20 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..63683e3865 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,24 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/OneOperandCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..6498b64289 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..0a5987e4c3 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..b423f989ae --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package org.xukai.jvm.cmd; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.ClassInfo; +import org.xukai.jvm.constant.ConstantInfo; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.FieldRefInfo; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java index bf7171a966..1adde177f3 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java @@ -15,7 +15,12 @@ public void setUtf8Index(int utf8Index) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } + public String getClassName() { int index = getUtf8Index(); UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java index 24323692e9..ffae0e4e83 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java @@ -25,5 +25,24 @@ public ConstantPool getConstantPool() { public ConstantInfo getConstantInfo(int index){ return this.constantPool.getConstantInfo(index); } + + public abstract void accept(Visitor visitor); + + public static interface Visitor { + + public void visitString(StringInfo info); + + public void visitNameAndType(NameAndTypeInfo info); + + public void visitMethodRef(MethodRefInfo info); + + public void visitFieldRef(FieldRefInfo info); + + public void visitClassInfo(ClassInfo info); + + public void visistUTF8(UTF8Info info); + + + } } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java index ff4aa4b906..d9cc6f0f56 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java @@ -23,7 +23,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java index f0b846f47c..d9b5281155 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java @@ -11,7 +11,12 @@ public FieldRefInfo(ConstantPool pool) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java index a0c02fedaf..28b80235d9 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java @@ -14,7 +14,12 @@ public MethodRefInfo(ConstantPool pool) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java index c88c848d3a..66d235641d 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java @@ -25,8 +25,13 @@ public void setIndex2(int index2) { public int getType() { return type; } - - + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } + + public String getName(){ ConstantPool pool = this.getConstantPool(); UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java index 0aa452b866..732e8a42cf 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java @@ -9,5 +9,10 @@ public NullConstantInfo(){ public int getType() { return -1; } - + + @Override + public void accept(Visitor visitor) { + + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java index 31a3c52910..0fc28b142c 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java @@ -10,7 +10,12 @@ public StringInfo(ConstantPool pool) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + } + public int getIndex() { return index; } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java index caf1c19918..ae5200371e 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java @@ -16,6 +16,12 @@ public void setLength(int length) { public int getType() { return type; } + + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } + @Override public String toString() { return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java index 6cd71db72c..27585d73b1 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java @@ -4,6 +4,7 @@ import org.xukai.jvm.attr.AttributeInfo; import org.xukai.jvm.attr.CodeAttr; import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.cmd.ByteCodeCommand; import org.xukai.jvm.constant.UTF8Info; import org.xukai.jvm.loader.ByteCodeIterator; @@ -25,6 +26,7 @@ public ClassFile getClzFile() { public int getNameIndex() { return nameIndex; } + public int getDescriptorIndex() { return descriptorIndex; } @@ -55,6 +57,10 @@ public String getMethodName(){ public String getMethodDescription(){ return ((UTF8Info)clzFile.getConstantPool().getConstantInfo(this.descriptorIndex)).getValue(); } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } @@ -77,12 +83,5 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ } - public static void main(String[] args) { - CodeAttr codeAttr = new CodeAttr(1, 1, 1, 1, 1, ""); - System.out.println(codeAttr instanceof AttributeInfo); - AttributeInfo codeAttr2 = new CodeAttr(1, 1, 1, 1, 1, ""); - System.out.println(codeAttr2 instanceof CodeAttr); - } - } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ClassFilePrinter.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..4c78dc1796 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ClassFilePrinter.java @@ -0,0 +1,48 @@ +package org.xukai.jvm.print; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.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 = "D:\\java\\IDEA-Workspace\\coding2017\\group19\\527220084\\xukai_coding\\coding-common\\target\\classes"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "org.xukai.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ConstantPoolPrinter.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..b1ec2eda79 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,85 @@ +package org.xukai.jvm.print; + + +import org.xukai.jvm.constant.ClassInfo; +import org.xukai.jvm.constant.ConstantInfo; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.FieldRefInfo; +import org.xukai.jvm.constant.MethodRefInfo; +import org.xukai.jvm.constant.NameAndTypeInfo; +import org.xukai.jvm.constant.StringInfo; +import org.xukai.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()).append(" ").append(info.getClassName()).append(".").append + (info.getMethodName()).append(info.getParamAndReturnType()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i <= pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java index c4fad12ff6..08e65bedce 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java @@ -8,6 +8,10 @@ import org.junit.Test; import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.clz.ClassIndex; +import org.xukai.jvm.cmd.BiPushCmd; +import org.xukai.jvm.cmd.ByteCodeCommand; +import org.xukai.jvm.cmd.OneOperandCmd; +import org.xukai.jvm.cmd.TwoOperandCmd; import org.xukai.jvm.constant.ClassInfo; import org.xukai.jvm.constant.ConstantPool; import org.xukai.jvm.constant.MethodRefInfo; @@ -303,7 +307,82 @@ 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); + } + + } From fe49c69448ba4d9cfda6cc2ce0af641237b06814 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Sat, 22 Apr 2017 19:18:06 +0800 Subject: [PATCH 101/151] seventh homework finished --- .../src/com/donaldy/jvm/attr/CodeAttr.java | 63 +++++++++- .../src/com/donaldy/jvm/clz/ClassFile.java | 19 +++ .../com/donaldy/jvm/cmd/CommandParser.java | 77 +++++++++++- .../com/donaldy/jvm/constant/ClassInfo.java | 4 + .../donaldy/jvm/constant/ConstantInfo.java | 11 ++ .../donaldy/jvm/constant/ConstantPool.java | 4 +- .../donaldy/jvm/constant/FieldRefInfo.java | 4 + .../donaldy/jvm/constant/MethodRefInfo.java | 5 + .../donaldy/jvm/constant/NameAndTypeInfo.java | 6 + .../jvm/constant/NullConstantInfo.java | 4 + .../com/donaldy/jvm/constant/StringInfo.java | 6 + .../com/donaldy/jvm/constant/UTF8Info.java | 5 + .../donaldy/jvm/loader/ClassFileLoader.java | 1 + .../src/com/donaldy/jvm/method/Method.java | 39 +++++- .../donaldy/jvm/print/ClassFilePrinter.java | 10 +- .../jvm/print/ConstantPoolPrinter.java | 116 +++++++++++++++++- .../donaldy/jvm/test/ClassFileloaderTest.java | 4 + 17 files changed, 359 insertions(+), 19 deletions(-) diff --git a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java index 22e48645be..9122f3690a 100644 --- a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java +++ b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java @@ -2,6 +2,7 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.cmd.ByteCodeCommand; +import com.donaldy.jvm.cmd.CommandParser; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.loader.ByteCodeIterator; @@ -16,9 +17,11 @@ public String getCode() { } private ByteCodeCommand[] cmds ; + public ByteCodeCommand[] getCmds() { return cmds; } + private LineNumberTable lineNumTable; private LocalVariableTable localVarTable; private StackMapTable stackMapTable; @@ -41,12 +44,63 @@ 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); + + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code,cmds); + + 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); - return null; + //已经向前移动了U2, 现在退回去。 + iter.back(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){ + public String toString(ConstantPool pool) { + StringBuilder buffer = new StringBuilder(); //buffer.append("Code:").append(code).append("\n"); for(int i=0;i 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()); + + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(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 implement."); + } + } + + calcuateOffset(cmds); + + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; } private static void calcuateOffset(List cmds) { diff --git a/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java index 71f31261e4..cbf71927be 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java @@ -21,4 +21,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/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java index 20cad6fcd5..ff2a27bcd6 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java @@ -26,4 +26,15 @@ 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); + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java b/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java index 77bdfc8e67..1698c2c657 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java @@ -23,7 +23,9 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } + + } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java index 6a6f72f5da..ffd7b835e0 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java @@ -51,4 +51,8 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java index e65135279f..b370eff575 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java @@ -49,6 +49,11 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java index 21ecd2b411..db48418b57 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java @@ -42,4 +42,10 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java index 3a2cc11017..74e491637f 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java @@ -9,5 +9,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java index f59d34a497..94325bfdbc 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java @@ -22,5 +22,11 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java b/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java index 7432e5b6c4..10c06dcf2a 100644 --- a/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java +++ b/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java @@ -26,6 +26,11 @@ public String getValue() { public void setValue(String value) { this.value = value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } diff --git a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java index e1132dd023..17f25799c2 100644 --- a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java +++ b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java @@ -58,6 +58,7 @@ public String getClassPath() { } public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); ClassFileParser parser = new ClassFileParser(); return parser.parse(codes); diff --git a/group24/448641125/src/com/donaldy/jvm/method/Method.java b/group24/448641125/src/com/donaldy/jvm/method/Method.java index 603e773b87..8720da21b7 100644 --- a/group24/448641125/src/com/donaldy/jvm/method/Method.java +++ b/group24/448641125/src/com/donaldy/jvm/method/Method.java @@ -49,8 +49,42 @@ public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorInd public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + + /*System.out.println("name = " + clzFile.getConstantPool().getUTF8String(nameIndex) + + ", desc = " + clzFile.getConstantPool().getUTF8String(descIndex));*/ + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + //attribCount == 1 + for( int j = 1; j <= attribCount; j++){ + + int attrNameIndex = iter.nextU2ToInt(); + /*System.out.println("attrNameIndex : " + attrNameIndex);*/ + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + /*System.out.println("attrName : " + attrName);*/ + iter.back(2); + + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + /*System.out.println("j : " + j );*/ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else{ + throw new RuntimeException("only CODE attribute is implemented , please implement the "+ attrName); + } + + } + + return m ; + + //////////////////////Backup/////////////////////// + /*int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); int descriptorIndex = iter.nextU2ToInt(); int attributeCount = iter.nextU2ToInt(); @@ -60,6 +94,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ if (!"Code".equals(clzFile.getConstantPool().getUTF8String(attrNameIndex))) throw new RuntimeException("attributeInfo : " + attrNameIndex); + //CodeAttr.parse int attrLen = iter.nextU4ToInt(); int maxStack = iter.nextU2ToInt(); int maxLocals = iter.nextU2ToInt(); @@ -84,7 +119,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); method.setCodeAttr(codeAttr); - return method; + return method;*/ } @@ -105,6 +140,8 @@ public String toString() { } public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java b/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java index 26e9d183d4..740a9aa9aa 100644 --- a/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java +++ b/group24/448641125/src/com/donaldy/jvm/print/ClassFilePrinter.java @@ -29,21 +29,19 @@ public void print(){ System.out.println("minor version:" + clzFile.getMinorVersion()); - System.out.println("major version:" + clzFile.getMinorVersion()); + System.out.println("major version:" + clzFile.getMajorVersion()); 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"; + String path = "D:\\tools\\Code\\Y_Repository\\coding2017\\group24\\448641125\\out\\production\\448641125\\"; ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "com.donaldy.jvm.test.EmployeeV1"; ClassFile clzFile = loader.loadClass(className); diff --git a/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java b/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java index 7070d5766e..910494d803 100644 --- a/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java +++ b/group24/448641125/src/com/donaldy/jvm/print/ConstantPoolPrinter.java @@ -1,5 +1,7 @@ package com.donaldy.jvm.print; +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.clz.ClassIndex; import com.donaldy.jvm.constant.ClassInfo; import com.donaldy.jvm.constant.ConstantInfo; import com.donaldy.jvm.constant.ConstantPool; @@ -15,11 +17,117 @@ public class ConstantPoolPrinter { this.pool = pool; } public void print(){ - + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } + /*public void print(){ + System.out.println("Constant Pool:"); + + for (int i = 0; i <= this.pool.getSize(); ++i) { + ConstantInfo cnstInfo = this.pool.getConstantInfo(i); + + if (cnstInfo instanceof ClassInfo) { + ClassInfo info = (ClassInfo)cnstInfo; + + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + } + + if (cnstInfo instanceof UTF8Info) { + + UTF8Info info = (UTF8Info) cnstInfo; + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + } + + + + *//*int type = constInfo.getType(); + System.out.println("type : " + type); + + if (type == ClassInfo.UTF8_INFO) { + + } else if (type == ClassInfo.FLOAT_INFO) { + + } else if (type == ClassInfo.CLASS_INFO) { + + } else if (type == ClassInfo.STRING_INFO) { + + } else if (type == ClassInfo.FIELD_INFO) { + + } else if (type == ClassInfo.METHOD_INFO) { + + } else if (type == ClassInfo.NAME_AND_TYPE_INFO) { + + }*//* + } - - - } + }*/ } diff --git a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java index 0884878010..7c30dedb17 100644 --- a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java +++ b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java @@ -288,6 +288,10 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName @Test public void testByteCodeCommand(){ { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + this.clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); ByteCodeCommand [] cmds = initMethod.getCmds(); From 6aa54b1dc202e4af1814fa4e5fc0c24820ea9167 Mon Sep 17 00:00:00 2001 From: gongxun Date: Sat, 22 Apr 2017 21:51:22 +0800 Subject: [PATCH 102/151] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/2.26/list/ArrayList.java | 14 +++++--- group17/785396327/4.9/expr/PostfixExpr.java | 34 ++++++++++++++++++- group17/785396327/4.9/expr/PrefixExpr.java | 34 ++++++++++++++++++- .../785396327/4.9/expr/PrefixExprTest.java | 6 ++-- group17/785396327/4.9/expr/TokenParser.java | 2 +- .../785396327/4.9/expr/TokenParserTest.java | 7 ++++ 6 files changed, 86 insertions(+), 11 deletions(-) diff --git a/group17/785396327/2.26/list/ArrayList.java b/group17/785396327/2.26/list/ArrayList.java index 119079f7ce..dcdc1264b0 100644 --- a/group17/785396327/2.26/list/ArrayList.java +++ b/group17/785396327/2.26/list/ArrayList.java @@ -1,5 +1,7 @@ package list; +import org.junit.Test; + import java.util.Arrays; import java.util.NoSuchElementException; @@ -34,12 +36,12 @@ public boolean add(T ele) { } public T get(int index) { - checkBounds(index); + checkBounds(index, false); return (T) elementData[index]; } public T remove(int index) { - checkBounds(index); + checkBounds(index, false); T removeEle = (T) elementData[index]; System.arraycopy(elementData, index + 1, elementData, index, size - index); size--; @@ -47,7 +49,7 @@ public T remove(int index) { } public boolean add(int index, T ele) { - checkBounds(index); + checkBounds(index, true); grow(size++); //将原本数组从待插入的index截取,将原本index后的有效值,复制到原本数组index+1之后 System.arraycopy(elementData, index, elementData, index + 1, size - index); @@ -65,8 +67,10 @@ public boolean remove(T ele) { return true; } - private void checkBounds(int index) { - if (index < 0 || index >= size) + private void checkBounds(int index, boolean isAdd) { + if (isAdd && (index < 0 || index > size)) { + throw new IndexOutOfBoundsException("index : " + index + ", size : [ 0 - " + size + " ]"); + } else if (!isAdd && (index < 0 || index >= size)) throw new IndexOutOfBoundsException("index : " + index + ", size : [ 0 - " + size + " ]"); } diff --git a/group17/785396327/4.9/expr/PostfixExpr.java b/group17/785396327/4.9/expr/PostfixExpr.java index a6d19be939..c22b7788aa 100644 --- a/group17/785396327/4.9/expr/PostfixExpr.java +++ b/group17/785396327/4.9/expr/PostfixExpr.java @@ -1,5 +1,9 @@ package expr; +import stack.MyStack; + +import java.util.List; + /** * Created by gongxun on 2017/4/22. */ @@ -11,6 +15,34 @@ public PostfixExpr(String expr) { } public float evaluate() { - return 0.0f; + TokenParser tokenParser = new TokenParser(); + if (expr == null) + throw new RuntimeException("wrong expr !"); + MyStack stack = new MyStack(); + List tokens = tokenParser.parse(expr); + if (tokens != null) { + for (Token token : tokens) { + if (token.isNumber()) + stack.push(((Integer) token.getIntValue()).floatValue()); + else { + Float value = calcValue(token, stack); + stack.push(value); + } + } + } + return stack.pop(); + } + + private Float calcValue(Token token, MyStack stack) { + String operator = token.toString(); + Float rightNum = stack.pop(); + Float leftNum = stack.pop(); + if (operator.equals("+")) + return leftNum + rightNum; + else if (operator.equals("-")) + return leftNum - rightNum; + else if (operator.equals("*")) + return leftNum * rightNum; + return leftNum / rightNum; } } diff --git a/group17/785396327/4.9/expr/PrefixExpr.java b/group17/785396327/4.9/expr/PrefixExpr.java index e86d6463c0..b29ffa0c64 100644 --- a/group17/785396327/4.9/expr/PrefixExpr.java +++ b/group17/785396327/4.9/expr/PrefixExpr.java @@ -1,7 +1,12 @@ package expr; +import stack.MyStack; + +import java.util.List; + /** * Created by gongxun on 2017/4/22. + * 从后向前遍历入栈 */ public class PrefixExpr { String expr = null; @@ -11,6 +16,33 @@ public PrefixExpr(String expr) { } public float evaluate() { - return 0.0f; + TokenParser tokenParser = new TokenParser(); + if (expr == null) + throw new RuntimeException("wrong expr !"); + MyStack stack = new MyStack(); + List tokens = tokenParser.parse(expr); + for (int i = tokens.size() - 1; i >= 0; i--) { + Token token = tokens.get(i); + if (token.isNumber()) + stack.push(((Integer) token.getIntValue()).floatValue()); + else { + Float value = calcValue(stack, token.toString()); + stack.push(value); + } + } + return stack.pop(); + } + + + private Float calcValue(MyStack stack, String operator) { + Float leftNum = stack.pop(); + Float rightNum = stack.pop(); + if (operator.equals("+")) + return leftNum + rightNum; + else if (operator.equals("-")) + return leftNum - rightNum; + else if (operator.equals("*")) + return leftNum * rightNum; + return leftNum / rightNum; } } diff --git a/group17/785396327/4.9/expr/PrefixExprTest.java b/group17/785396327/4.9/expr/PrefixExprTest.java index c2574eb155..326bfd9f2c 100644 --- a/group17/785396327/4.9/expr/PrefixExprTest.java +++ b/group17/785396327/4.9/expr/PrefixExprTest.java @@ -27,17 +27,17 @@ public void testEvaluate() { { // 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); + 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); + 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); + Assert.assertEquals(16, expr.evaluate(), 0.001f); } diff --git a/group17/785396327/4.9/expr/TokenParser.java b/group17/785396327/4.9/expr/TokenParser.java index 5620ad9f50..6c54890a42 100644 --- a/group17/785396327/4.9/expr/TokenParser.java +++ b/group17/785396327/4.9/expr/TokenParser.java @@ -31,7 +31,7 @@ public List parse(String expr) { i = nextOperatorIndex; } else{ - System.out.println("char :["+c+"] is not number or operator,ignore"); +// System.out.println("char :["+c+"] is not number or operator,ignore"); i++; } diff --git a/group17/785396327/4.9/expr/TokenParserTest.java b/group17/785396327/4.9/expr/TokenParserTest.java index 22fe16dc85..793ba1fe0b 100644 --- a/group17/785396327/4.9/expr/TokenParserTest.java +++ b/group17/785396327/4.9/expr/TokenParserTest.java @@ -37,4 +37,11 @@ public void test() { Assert.assertEquals("/", tokens.get(9).toString()); Assert.assertEquals(4, tokens.get(10).getIntValue()); } + + @Test + public void testPostfixExprParser() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse("6 5 2 3 + 8 * + 3 + *"); + System.out.println(tokens); + } } From 7b9535d24267a05113e2217ca7576ef3940b2d4c Mon Sep 17 00:00:00 2001 From: onlyLYJ Date: Sun, 23 Apr 2017 08:52:38 +0800 Subject: [PATCH 103/151] Token parser done --- .../coding/basic/stack/expr/InfixExpr.java | 180 ++++++++---------- .../coding/basic/stack/expr/InfixExprS.java | 102 ++++++++++ .../basic/stack/expr/InfixExprTest.java | 4 +- .../basic/stack/expr/InfixToPostfix.java | 43 ++++- .../coding/basic/stack/expr/PostfixExpr.java | 35 +++- .../coding/basic/stack/expr/PrefixExpr.java | 40 +++- .../coding/basic/stack/expr/Token.java | 29 ++- .../basic/stack/expr/TokenParserTest.java | 25 +++ .../jvm/print/ConstantPoolPrinter.java | 2 +- 9 files changed, 349 insertions(+), 111 deletions(-) create mode 100644 group12/382266293/coding/basic/stack/expr/InfixExprS.java diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java index 0d23091ab1..c143116ec4 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -1,102 +1,78 @@ -package stack.expr; - -import java.util.Stack; -import stack.StackUtil; - -public class InfixExpr { - String expr = null; - - public InfixExpr(String expr) { - this.expr = expr; - } - - public float evaluate() { - - TParser tp = new TParser(); - tp.parse(expr); - Stack ints = new Stack(); - Stack signs = new Stack(); - - int i1 = tp.nextInt(); - String sign1 = tp.nextSign(); - - ints.push(i1); - signs.push(sign1); - - while (tp.hasNextInt()) { - - int i2 = tp.nextInt(); - String sign2 = tp.nextSign(); - - if (tp.hasNextInt()) { - - if (highPrioritySign(sign1)) { - - i1 = ints.pop(); - sign1 = signs.pop(); - i2 = calculate(i1, i2, sign1); - - } - - ints.push(i2); - signs.push(sign2); - sign1 = sign2; - - } - - } - - signs.pop(); - StackUtil.reverse(ints); - StackUtil.reverse(signs); - - while (!ints.isEmpty()) { - - int firstInt = ints.pop(); - - if (ints.isEmpty()) { - return (float) firstInt; - } - - int secInt = ints.pop(); - String sign = signs.pop(); - int result = calculate(firstInt, secInt, sign); - ints.push(result); - - } - - System.out.println("we shall not reach here"); - return (float) ints.peek(); - } - - private int calculate(int firstInt, int secInt, String lowsign) { - - int result; - if (lowsign.equals("+")) { - result = firstInt + secInt; - } else if (lowsign.equals("-")) { - result = firstInt - secInt; - } else if (lowsign.equals("*")) { - result = firstInt * secInt; - } else if (lowsign.equals("/")) { - result = firstInt / secInt; - } else { - throw new RuntimeException(lowsign + " has not been supported yet!"); - } - - return result; - - } - - private boolean highPrioritySign(String sign) { - - if (sign.equals("*") || sign.equals("/")) { - - return true; - - } - - return false; - } - -} +package stack.expr; + +import java.util.List; +import java.util.Stack; + + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + if(opStack.isEmpty()){ + + opStack.push(token); + } else{ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + 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"); + } + + + +} diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprS.java b/group12/382266293/coding/basic/stack/expr/InfixExprS.java new file mode 100644 index 0000000000..7600cccb93 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/InfixExprS.java @@ -0,0 +1,102 @@ +package stack.expr; + +import java.util.Stack; +import stack.StackUtil; + +public class InfixExprS{ + String expr = null; + + public InfixExprS(String expr) { + this.expr = expr; + } + + public float evaluate() { + + TParser tp = new TParser(); + tp.parse(expr); + Stack ints = new Stack(); + Stack signs = new Stack(); + + int i1 = tp.nextInt(); + String sign1 = tp.nextSign(); + + ints.push(i1); + signs.push(sign1); + + while (tp.hasNextInt()) { + + int i2 = tp.nextInt(); + String sign2 = tp.nextSign(); + + if (tp.hasNextInt()) { + + if (highPrioritySign(sign1)) { + + i1 = ints.pop(); + sign1 = signs.pop(); + i2 = calculate(i1, i2, sign1); + + } + + ints.push(i2); + signs.push(sign2); + sign1 = sign2; + + } + + } + + signs.pop(); + StackUtil.reverse(ints); + StackUtil.reverse(signs); + + while (!ints.isEmpty()) { + + int firstInt = ints.pop(); + + if (ints.isEmpty()) { + return (float) firstInt; + } + + int secInt = ints.pop(); + String sign = signs.pop(); + int result = calculate(firstInt, secInt, sign); + ints.push(result); + + } + + System.out.println("we shall not reach here"); + return (float) ints.peek(); + } + + private int calculate(int firstInt, int secInt, String lowsign) { + + int result; + if (lowsign.equals("+")) { + result = firstInt + secInt; + } else if (lowsign.equals("-")) { + result = firstInt - secInt; + } else if (lowsign.equals("*")) { + result = firstInt * secInt; + } else if (lowsign.equals("/")) { + result = firstInt / secInt; + } else { + throw new RuntimeException(lowsign + " has not been supported yet!"); + } + + return result; + + } + + private boolean highPrioritySign(String sign) { + + if (sign.equals("*") || sign.equals("/")) { + + return true; + + } + + return false; + } + +} diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java index 791ea67e43..836848ac91 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -34,8 +34,8 @@ public void testEvaluate() { } { - InfixExpr expr = new InfixExpr("2+3*4/2"); - Assert.assertEquals(8.0, expr.evaluate(), 0.001f); + InfixExpr expr = new InfixExpr("2+3*4/2+1"); + Assert.assertEquals(9, expr.evaluate(), 0.001f); } { diff --git a/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java b/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java index 790984607f..a293ddfeee 100644 --- a/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java +++ b/group12/382266293/coding/basic/stack/expr/InfixToPostfix.java @@ -1,14 +1,51 @@ package stack.expr; import java.util.List; +import java.util.Stack; public class InfixToPostfix { public static List convert(String expr) { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + List pTokens = new Stack<>(); + Stack opStack = new Stack<>(); + + for (Token token : tokens) { + if (token.isNumber()) { + pTokens.add(token); + } else { + if (token.isLeftSquare()) { + opStack.push(token); + } else if (token.isRightSquare()) { + while (!opStack.peek().isLeftSquare()) { + pTokens.add(opStack.pop()); + } + opStack.pop(); + } else { + if (opStack.isEmpty() || token.hasHigherPriority(opStack.peek())) { + opStack.add(token); + } else { + while (!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())) { + pTokens.add(opStack.pop()); + } + opStack.add(token); + } + } + } + } - return null; + while(!opStack.isEmpty()) { + pTokens.add(opStack.pop()); + } + + System.out.println(pTokens); + return pTokens; } - - + public static void main(String[] args) { + convert("10-2*3+50"); + } + } diff --git a/group12/382266293/coding/basic/stack/expr/PostfixExpr.java b/group12/382266293/coding/basic/stack/expr/PostfixExpr.java index 30682ae05d..e4eaa4bfe6 100644 --- a/group12/382266293/coding/basic/stack/expr/PostfixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/PostfixExpr.java @@ -11,8 +11,41 @@ public PostfixExpr(String 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"); } + } diff --git a/group12/382266293/coding/basic/stack/expr/PrefixExpr.java b/group12/382266293/coding/basic/stack/expr/PrefixExpr.java index 96bef48492..1628810d68 100644 --- a/group12/382266293/coding/basic/stack/expr/PrefixExpr.java +++ b/group12/382266293/coding/basic/stack/expr/PrefixExpr.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.Stack; +import stack.StackUtil; + public class PrefixExpr { String expr = null; @@ -11,7 +13,43 @@ public PrefixExpr(String expr) { } public float evaluate() { - return 0.0f; + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + System.out.println(tokens); + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for(Token token : tokens){ + exprStack.push(token); + } + System.out.println(exprStack); + while(!exprStack.isEmpty()){ + Token t = exprStack.pop(); + if(t.isNumber()){ + numStack.push(new Float(t.getIntValue())); + }else{ + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.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"); } diff --git a/group12/382266293/coding/basic/stack/expr/Token.java b/group12/382266293/coding/basic/stack/expr/Token.java index 203f91d61f..670663d358 100644 --- a/group12/382266293/coding/basic/stack/expr/Token.java +++ b/group12/382266293/coding/basic/stack/expr/Token.java @@ -6,13 +6,15 @@ import java.util.Map; class Token { - public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + 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); + priorities.put("(", 0); + priorities.put(")", 3); } static final int OPERATOR = 1; static final int NUMBER = 2; @@ -30,6 +32,22 @@ public boolean isNumber() { public boolean isOperator() { return type == OPERATOR; } + + public boolean isLeftSquare() { + if (!isOperator()) { + return false; + } + + return priorities.get(this.value) == 0; + } + + public boolean isRightSquare() { + if (!isOperator()) { + return false; + } + + return priorities.get(this.value) == 3; + } public int getIntValue() { return Integer.valueOf(value).intValue(); @@ -38,12 +56,21 @@ 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; } + + public boolean isSquare() { + + return isLeftSquare() || isRightSquare(); + } + + diff --git a/group12/382266293/coding/basic/stack/expr/TokenParserTest.java b/group12/382266293/coding/basic/stack/expr/TokenParserTest.java index 22dd219fb7..427f887edd 100644 --- a/group12/382266293/coding/basic/stack/expr/TokenParserTest.java +++ b/group12/382266293/coding/basic/stack/expr/TokenParserTest.java @@ -37,5 +37,30 @@ public void test() { Assert.assertEquals("/", tokens.get(9).toString()); Assert.assertEquals(4, tokens.get(10).getIntValue()); } + + @Test + public void test1() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse("9+(3-1)*3+10/2"); + System.out.println(tokens); +// //9+(3-1)*3+10/2 +// PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); +// Assert.assertEquals(20, expr.evaluate(),0.0f); [9, 3, 1, -, 3, *, +, 10, 2, /, +] + +// 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()); + } + + } diff --git a/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java index be07ccd496..012aeb7001 100644 --- a/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java +++ b/group12/382266293/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -25,7 +25,7 @@ public void print(){ for (int i = 1; i <= size; i++) { ConstantInfo info = pool.getConstantInfo(i); - System.out.print("#" + i + " ="); + System.out.print("#" + i + " = "); info.accept(this); } From bbc13347daf4ec2dfe09835e2c6cf369209a9bf4 Mon Sep 17 00:00:00 2001 From: jy <977996067@qq.com> Date: Sun, 23 Apr 2017 13:45:13 +0800 Subject: [PATCH 104/151] =?UTF-8?q?4.23=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/task7/expr/InfixExpr.java | 79 ++++++++ .../src/task7/expr/InfixExprTest.java | 56 +++++ .../src/task7/expr/PostfixExpr.java | 45 +++++ .../src/task7/expr/PostfixExprTest.java | 37 ++++ .../src/task7/expr/PrefixExpr.java | 47 +++++ .../src/task7/expr/PrefixExprTest.java | 44 ++++ .../1507_977996067/src/task7/expr/Token.java | 53 +++++ .../src/task7/expr/TokenParser.java | 57 ++++++ .../src/task7/jvm/attr/AttributeInfo.java | 19 ++ .../src/task7/jvm/attr/CodeAttr.java | 120 +++++++++++ .../src/task7/jvm/attr/LineNumberTable.java | 72 +++++++ .../src/task7/jvm/attr/LocalVariableItem.java | 39 ++++ .../task7/jvm/attr/LocalVariableTable.java | 57 ++++++ .../src/task7/jvm/attr/StackMapTable.java | 30 +++ .../src/task7/jvm/clz/AccessFlag.java | 25 +++ .../src/task7/jvm/clz/ClassFile.java | 134 ++++++++++++ .../src/task7/jvm/clz/ClassIndex.java | 19 ++ .../src/task7/jvm/cmd/BiPushCmd.java | 23 +++ .../src/task7/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++ .../src/task7/jvm/cmd/CommandParser.java | 124 ++++++++++++ .../src/task7/jvm/cmd/GetFieldCmd.java | 22 ++ .../src/task7/jvm/cmd/GetStaticFieldCmd.java | 23 +++ .../src/task7/jvm/cmd/InvokeSpecialCmd.java | 23 +++ .../src/task7/jvm/cmd/InvokeVirtualCmd.java | 22 ++ .../src/task7/jvm/cmd/LdcCmd.java | 29 +++ .../src/task7/jvm/cmd/NewObjectCmd.java | 19 ++ .../src/task7/jvm/cmd/NoOperandCmd.java | 23 +++ .../src/task7/jvm/cmd/OneOperandCmd.java | 27 +++ .../src/task7/jvm/cmd/PutFieldCmd.java | 19 ++ .../src/task7/jvm/cmd/TwoOperandCmd.java | 67 ++++++ .../src/task7/jvm/constant/ClassInfo.java | 31 +++ .../src/task7/jvm/constant/ConstantInfo.java | 35 ++++ .../src/task7/jvm/constant/ConstantPool.java | 37 ++++ .../src/task7/jvm/constant/FieldRefInfo.java | 65 ++++++ .../src/task7/jvm/constant/MethodRefInfo.java | 65 ++++++ .../task7/jvm/constant/NameAndTypeInfo.java | 56 +++++ .../task7/jvm/constant/NullConstantInfo.java | 21 ++ .../src/task7/jvm/constant/StringInfo.java | 35 ++++ .../src/task7/jvm/constant/UTF8Info.java | 45 +++++ .../src/task7/jvm/field/Field.java | 48 +++++ .../task7/jvm/loader/ByteCodeIterator.java | 56 +++++ .../src/task7/jvm/loader/ClassFileLoader.java | 122 +++++++++++ .../src/task7/jvm/loader/ClassFileParser.java | 112 ++++++++++ .../src/task7/jvm/method/Method.java | 91 +++++++++ .../src/task7/jvm/print/ClassFilePrinter.java | 44 ++++ .../task7/jvm/print/ConstantInfoVisitor.java | 18 ++ .../jvm/print/ConstantInfoVisitorImpl.java | 51 +++++ .../task7/jvm/print/ConstantPoolPrinter.java | 26 +++ .../task7/jvm/test/ClassFileloaderTest.java | 191 ++++++++++++++++++ .../src/task7/jvm/test/EmployeeV1.java | 29 +++ .../src/task7/jvm/util/Util.java | 23 +++ 51 files changed, 2683 insertions(+) create mode 100644 group15/1507_977996067/src/task7/expr/InfixExpr.java create mode 100644 group15/1507_977996067/src/task7/expr/InfixExprTest.java create mode 100644 group15/1507_977996067/src/task7/expr/PostfixExpr.java create mode 100644 group15/1507_977996067/src/task7/expr/PostfixExprTest.java create mode 100644 group15/1507_977996067/src/task7/expr/PrefixExpr.java create mode 100644 group15/1507_977996067/src/task7/expr/PrefixExprTest.java create mode 100644 group15/1507_977996067/src/task7/expr/Token.java create mode 100644 group15/1507_977996067/src/task7/expr/TokenParser.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/AttributeInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/CodeAttr.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/LineNumberTable.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/LocalVariableItem.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/LocalVariableTable.java create mode 100644 group15/1507_977996067/src/task7/jvm/attr/StackMapTable.java create mode 100644 group15/1507_977996067/src/task7/jvm/clz/AccessFlag.java create mode 100644 group15/1507_977996067/src/task7/jvm/clz/ClassFile.java create mode 100644 group15/1507_977996067/src/task7/jvm/clz/ClassIndex.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/BiPushCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/ByteCodeCommand.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/CommandParser.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/GetFieldCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/LdcCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/NewObjectCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/NoOperandCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/OneOperandCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/PutFieldCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/cmd/TwoOperandCmd.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/ClassInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/ConstantInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/ConstantPool.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/FieldRefInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/MethodRefInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/NameAndTypeInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/NullConstantInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/StringInfo.java create mode 100644 group15/1507_977996067/src/task7/jvm/constant/UTF8Info.java create mode 100644 group15/1507_977996067/src/task7/jvm/field/Field.java create mode 100644 group15/1507_977996067/src/task7/jvm/loader/ByteCodeIterator.java create mode 100644 group15/1507_977996067/src/task7/jvm/loader/ClassFileLoader.java create mode 100644 group15/1507_977996067/src/task7/jvm/loader/ClassFileParser.java create mode 100644 group15/1507_977996067/src/task7/jvm/method/Method.java create mode 100644 group15/1507_977996067/src/task7/jvm/print/ClassFilePrinter.java create mode 100644 group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitor.java create mode 100644 group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitorImpl.java create mode 100644 group15/1507_977996067/src/task7/jvm/print/ConstantPoolPrinter.java create mode 100644 group15/1507_977996067/src/task7/jvm/test/ClassFileloaderTest.java create mode 100644 group15/1507_977996067/src/task7/jvm/test/EmployeeV1.java create mode 100644 group15/1507_977996067/src/task7/jvm/util/Util.java diff --git a/group15/1507_977996067/src/task7/expr/InfixExpr.java b/group15/1507_977996067/src/task7/expr/InfixExpr.java new file mode 100644 index 0000000000..1a18634382 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/InfixExpr.java @@ -0,0 +1,79 @@ +package task7.expr; + +import org.junit.Assert; +import task5.stack.Stack; + +import java.util.Arrays; + +public class InfixExpr { + + private String expr; + + private Stack numberStack = new Stack<>(); + + private Stack resultStack = new Stack<>(); + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + Assert.assertNotNull(expr); + + String[] operators = expr.split("[\\d]+"); + + int length = operators.length; + + Arrays.stream(expr.split("[+\\-*/]+")) + .map(Float::parseFloat) + .forEach(numberStack::push); + + numberStack = reverse(numberStack); + + resultStack.push(numberStack.pop()); + + for (int i = 1; i < length; i++) { + String currentOperator = operators[i]; +// 先做乘除,结果放resultStack里面 + switch (currentOperator) { + case "*": + resultStack.push(resultStack.pop() * numberStack.pop()); + break; + case "/": + resultStack.push(resultStack.pop() / numberStack.pop()); + break; + case "+": + resultStack.push(numberStack.pop()); + break; + case "-": + resultStack.push(numberStack.pop()); + break; + } + } + + resultStack = reverse(resultStack); + +// 做加减 + for (int i = 1; i < length; i++) { + String currentOperator = operators[i]; + if ("+".equals(currentOperator)) { + Float num1 = resultStack.pop(); + Float num2 = resultStack.pop(); + resultStack.push(num1 + num2); + } else if ("-".equals(currentOperator)) { + Float num1 = resultStack.pop(); + Float num2 = resultStack.pop(); + resultStack.push(num1 - num2); + } + } + return resultStack.peek(); + } + + private Stack reverse(Stack stackToReverse) { + Stack temp = new Stack<>(); + while (!stackToReverse.isEmpty()) + temp.push(stackToReverse.pop()); + return temp; + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/expr/InfixExprTest.java b/group15/1507_977996067/src/task7/expr/InfixExprTest.java new file mode 100644 index 0000000000..f9eb14cbdf --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/InfixExprTest.java @@ -0,0 +1,56 @@ +package task7.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + + @Test + public void testExprSplit() { + String expr = "3*20+12*5-40/2"; + Arrays.stream(expr.split("[+\\-*/]+")).forEach(System.out::println); + Arrays.stream(expr.split("[\\d]+")).forEach(System.out::println); + } + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/expr/PostfixExpr.java b/group15/1507_977996067/src/task7/expr/PostfixExpr.java new file mode 100644 index 0000000000..369e52c203 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/PostfixExpr.java @@ -0,0 +1,45 @@ +package task7.expr; + +import task5.stack.Stack; + +import java.util.List; + +public class PostfixExpr { + private String expr = null; + + private Stack numberStack = new Stack<>(); + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List parse = new TokenParser().parse(expr); + for (int i = 0; i < parse.size(); i++) { + Token token = parse.get(i); +// 后缀表达式:从左向右遍历 遇到操作数入栈,遇到操作符弹出操作数栈的两个数计算再入栈 + if (token.isNumber()) + numberStack.push((float) token.getIntValue()); + else + numberStack.push(cal(token.toString(), numberStack.pop(), numberStack.pop())); + } + /*while (!operatorStack.isEmpty()) { + numberStack.push(cal(operatorStack.pop(), numberStack.pop(), numberStack.pop())); + }*/ + return numberStack.peek(); + } + + private static float cal(String operator, float var1, float var2) { + switch (operator) { + case "+": + return var2 + var1; + case "-": + return var2 - var1; + case "*": + return var2 * var1; + case "/": + return var2 / var1; + } + return -1; + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/expr/PostfixExprTest.java b/group15/1507_977996067/src/task7/expr/PostfixExprTest.java new file mode 100644 index 0000000000..172d397011 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/PostfixExprTest.java @@ -0,0 +1,37 @@ +package task7.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/group15/1507_977996067/src/task7/expr/PrefixExpr.java b/group15/1507_977996067/src/task7/expr/PrefixExpr.java new file mode 100644 index 0000000000..fe5cb137f0 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/PrefixExpr.java @@ -0,0 +1,47 @@ +package task7.expr; + +import task5.stack.Stack; + +import java.util.List; + +public class PrefixExpr { + + private String expr; + + private Stack numberStack = new Stack<>(); + + public PrefixExpr(String expr) { + this.expr = expr; + + } + + public float evaluate() { + List parse = new TokenParser().parse(expr); + for (int i = parse.size() - 1; i >= 0; i--) { + Token token = parse.get(i); +// 前缀表达式:从右向左遍历 遇到操作数入栈,遇到操作符弹出操作数栈的两个数计算再入栈 + if (token.isNumber()) + numberStack.push((float) token.getIntValue()); + else + numberStack.push(cal(token.toString(), numberStack.pop(), numberStack.pop())); + } + /*while (!operatorStack.isEmpty()) { + numberStack.push(cal(operatorStack.pop(), numberStack.pop(), numberStack.pop())); + }*/ + return numberStack.peek(); + } + + private static float cal(String operator, float var1, float var2) { + switch (operator) { + case "+": + return var1 + var2; + case "-": + return var1 - var2; + case "*": + return var1 * var2; + case "/": + return var1 / var2; + } + return -1; + } +} diff --git a/group15/1507_977996067/src/task7/expr/PrefixExprTest.java b/group15/1507_977996067/src/task7/expr/PrefixExprTest.java new file mode 100644 index 0000000000..9ac8f9936f --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/PrefixExprTest.java @@ -0,0 +1,44 @@ +package task7.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/group15/1507_977996067/src/task7/expr/Token.java b/group15/1507_977996067/src/task7/expr/Token.java new file mode 100644 index 0000000000..5ca7b1aef8 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/Token.java @@ -0,0 +1,53 @@ +package task7.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public 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 int getIntValue() { + return Integer.valueOf(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/group15/1507_977996067/src/task7/expr/TokenParser.java b/group15/1507_977996067/src/task7/expr/TokenParser.java new file mode 100644 index 0000000000..45d75ffc12 --- /dev/null +++ b/group15/1507_977996067/src/task7/expr/TokenParser.java @@ -0,0 +1,57 @@ +package task7.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/group15/1507_977996067/src/task7/jvm/attr/AttributeInfo.java b/group15/1507_977996067/src/task7/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..aba714c39b --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package task7.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/group15/1507_977996067/src/task7/jvm/attr/CodeAttr.java b/group15/1507_977996067/src/task7/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e3784bec44 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/CodeAttr.java @@ -0,0 +1,120 @@ +package task7.jvm.attr; + + +import task7.jvm.clz.ClassFile; +import task7.jvm.cmd.ByteCodeCommand; +import task7.jvm.cmd.CommandParser; +import task7.jvm.constant.ConstantPool; +import task7.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.next2Bytes(); + int attrLen = iter.next4Bytes(); + int maxStack = iter.next2Bytes(); + int maxLocals = iter.next2Bytes(); + int codeLen = iter.next4Bytes(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.next2Bytes(); + //TODO 处理exception + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.next2Bytes(); + + for (int x = 1; x <= subAttrCount; x++) { + int subAttrIndex = iter.next2Bytes(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(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 < cmds.length; i++) { + buffer.append(cmds[i].toString(pool)).append("\n"); + } + buffer.append("\n"); + buffer.append(this.lineNumTable.toString()); + buffer.append(this.localVarTable.toString(pool)); + return buffer.toString(); + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + +} diff --git a/group15/1507_977996067/src/task7/jvm/attr/LineNumberTable.java b/group15/1507_977996067/src/task7/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..ebaec852b9 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/LineNumberTable.java @@ -0,0 +1,72 @@ +package task7.jvm.attr; + +import task7.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTable extends AttributeInfo { + List 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.next2Bytes(); + int len = iter.next4Bytes(); + + LineNumberTable table = new LineNumberTable(index, len); + + int itemLen = iter.next2Bytes(); + + for (int i = 1; i <= itemLen; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.next2Bytes()); + item.setLineNum(iter.next2Bytes()); + 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/group15/1507_977996067/src/task7/jvm/attr/LocalVariableItem.java b/group15/1507_977996067/src/task7/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..fbb27e8812 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package task7.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/group15/1507_977996067/src/task7/jvm/attr/LocalVariableTable.java b/group15/1507_977996067/src/task7/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..7bcf199b3c --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package task7.jvm.attr; + + +import task7.jvm.constant.ConstantPool; +import task7.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.next2Bytes(); + int len = iter.next4Bytes(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.next2Bytes(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.next2Bytes()); + item.setLength(iter.next2Bytes()); + item.setNameIndex(iter.next2Bytes()); + item.setDescIndex(iter.next2Bytes()); + item.setIndex(iter.next2Bytes()); + 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/group15/1507_977996067/src/task7/jvm/attr/StackMapTable.java b/group15/1507_977996067/src/task7/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..f57144783d --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package task7.jvm.attr; + + +import task7.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.next2Bytes(); + int len = iter.next4Bytes(); + 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/group15/1507_977996067/src/task7/jvm/clz/AccessFlag.java b/group15/1507_977996067/src/task7/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..e333b4621d --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package task7.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/jvm/clz/ClassFile.java b/group15/1507_977996067/src/task7/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..1587998e29 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/clz/ClassFile.java @@ -0,0 +1,134 @@ +package task7.jvm.clz; + +import task7.jvm.constant.ClassInfo; +import task7.jvm.constant.ConstantPool; +import task7.jvm.field.Field; +import task7.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + private List fields = new ArrayList<>(); + private List methods = new ArrayList<>(); + + public void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public List getMethods() { + return methods; + } + + public void setMethods(List methods) { + this.methods = methods; + } + + public ClassIndex getClzIndex() { + return clzIndex; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + public ConstantPool getConstantPool() { + return pool; + } + + public int getMinorVersion() { + return minorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + public int getMajorVersion() { + return majorVersion; + } + + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + + 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()); + + + } + + public String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + public String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType) { + + for (Method method : methods) { + int nameIndex = method.getNameIndex(); + int descriptorIndex = method.getDescriptorIndex(); + String name = getConstantPool().getUTF8String(nameIndex); + String descriptor = getConstantPool().getUTF8String(descriptorIndex); + if (methodName.equalsIgnoreCase(name) && paramAndReturnType.equalsIgnoreCase(descriptor)) { + return method; + } + } + return null; + } + + public Method getMainMethod() { + + return getMethod("main", "([Ljava/lang/String;)"); + } +} diff --git a/group15/1507_977996067/src/task7/jvm/clz/ClassIndex.java b/group15/1507_977996067/src/task7/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..b4342d6557 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package task7.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/jvm/cmd/BiPushCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..b80f830944 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ConstantInfo; +import task7.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(); + } + + + +} diff --git a/group15/1507_977996067/src/task7/jvm/cmd/ByteCodeCommand.java b/group15/1507_977996067/src/task7/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..e4c9e2ac2d --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package task7.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ConstantInfo; +import task7.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); +} diff --git a/group15/1507_977996067/src/task7/jvm/cmd/CommandParser.java b/group15/1507_977996067/src/task7/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..f6a12e1701 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/CommandParser.java @@ -0,0 +1,124 @@ +package task7.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import task7.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) { + codes = codes.toUpperCase(); + System.out.println("=========> codes: " + codes); + CommandIterator iterator = new CommandIterator(codes); + List commands = new ArrayList<>(); + while (iterator.hasNext()) { + String opCode = iterator.next2CharAsString(); + switch (opCode) { + case new_object: + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, codes); + newObjectCmd.setOprand1(iterator.next2CharAsInt()); + newObjectCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(newObjectCmd); + break; + case ldc: + LdcCmd ldcCmd = new LdcCmd(clzFile, codes); + ldcCmd.setOperand(iterator.next2CharAsInt()); + commands.add(ldcCmd); + break; + case bipush: + BiPushCmd biPushCmd = new BiPushCmd(clzFile, codes); + biPushCmd.setOperand(iterator.next2CharAsInt()); + commands.add(biPushCmd); + break; + case invokespecial: + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, codes); + invokeSpecialCmd.setOprand1(iterator.next2CharAsInt()); + invokeSpecialCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(invokeSpecialCmd); + break; + case invokevirtual: + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, codes); + invokeVirtualCmd.setOprand1(iterator.next2CharAsInt()); + invokeVirtualCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(invokeVirtualCmd); + break; + default: + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, codes); + commands.add(noOperandCmd); + } + } + calcuateOffset(commands); + return commands.toArray(new ByteCodeCommand[commands.size()]); + } + + 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); + } + + } +} diff --git a/group15/1507_977996067/src/task7/jvm/cmd/GetFieldCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..531770d8b9 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/GetStaticFieldCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..7f43150ca2 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ClassInfo; +import task7.jvm.constant.ConstantPool; +import task7.jvm.constant.FieldRefInfo; +import task7.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); + } + +} diff --git a/group15/1507_977996067/src/task7/jvm/cmd/InvokeSpecialCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ffe71dfb15 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ConstantPool; +import task7.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); + } + + + +} diff --git a/group15/1507_977996067/src/task7/jvm/cmd/InvokeVirtualCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..de80616b39 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/LdcCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..143b070968 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ConstantInfo; +import task7.jvm.constant.ConstantPool; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/NewObjectCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..09ffc20c19 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/NoOperandCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..16810f3874 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/OneOperandCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..713610e243 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package task7.jvm.cmd; + +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/PutFieldCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..df2b895c03 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/cmd/TwoOperandCmd.java b/group15/1507_977996067/src/task7/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..9cf2fded56 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package task7.jvm.cmd; + +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ClassInfo; +import task7.jvm.constant.ConstantInfo; +import task7.jvm.constant.ConstantPool; +import task7.jvm.constant.FieldRefInfo; +import task7.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/group15/1507_977996067/src/task7/jvm/constant/ClassInfo.java b/group15/1507_977996067/src/task7/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..8c2af5157a --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/ClassInfo.java @@ -0,0 +1,31 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitClassInfo(this); + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/ConstantInfo.java b/group15/1507_977996067/src/task7/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..24922e29d3 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/ConstantInfo.java @@ -0,0 +1,35 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo() { + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + + public abstract int getType(); + + public abstract void accept(ConstantInfoVisitor visitor); + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/ConstantPool.java b/group15/1507_977996067/src/task7/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..485f0dd7c2 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/ConstantPool.java @@ -0,0 +1,37 @@ +package task7.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos; + + public ConstantPool() { + this.constantInfos = new ArrayList<>(); + } + + public ConstantPool(int size) { + this.constantInfos = new ArrayList<>(size); + + addConstantInfo(new NullConstantInfo()); + } + + public void addConstantInfo(ConstantInfo info) { + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantInfos.get(index); + } + + public String getUTF8String(int index) { + return ((UTF8Info) this.constantInfos.get(index)).getValue(); + } + + public Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/FieldRefInfo.java b/group15/1507_977996067/src/task7/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..01474d2dd6 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/FieldRefInfo.java @@ -0,0 +1,65 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitFieldRefInfo(this); + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString() { + + NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() + " : " + typeInfo.getName() + ":" + typeInfo.getTypeInfo() + "]"; + } + + public String getClassName() { + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info) this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName() { + NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType() { + NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/MethodRefInfo.java b/group15/1507_977996067/src/task7/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..104b798e59 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/MethodRefInfo.java @@ -0,0 +1,65 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitMethodRefInfo(this); + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString() { + + return getClassName() + " : " + this.getMethodName() + " : " + this.getParamAndReturnType(); + } + + public String getClassName() { + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName() { + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType() { + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/NameAndTypeInfo.java b/group15/1507_977996067/src/task7/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..18089a2008 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,56 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + + public void setIndex1(int index1) { + this.index1 = index1; + } + + public int getIndex2() { + return index2; + } + + public void setIndex2(int index2) { + this.index2 = index2; + } + + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitNameAndTypeInfo(this); + } + + + public String getName() { + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info) pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo() { + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info) pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString() { + return "(" + getName() + "," + getTypeInfo() + ")"; + } +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/NullConstantInfo.java b/group15/1507_977996067/src/task7/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..216b03a449 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/NullConstantInfo.java @@ -0,0 +1,21 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + // non impl + } + +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/StringInfo.java b/group15/1507_977996067/src/task7/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..0b601e3adb --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/StringInfo.java @@ -0,0 +1,35 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitStringInfo(this); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group15/1507_977996067/src/task7/jvm/constant/UTF8Info.java b/group15/1507_977996067/src/task7/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..53686ca0a8 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/constant/UTF8Info.java @@ -0,0 +1,45 @@ +package task7.jvm.constant; + +import task7.jvm.print.ConstantInfoVisitor; + +public class UTF8Info extends ConstantInfo { + private int type = ConstantInfo.UTF8_INFO; + private int length; + private String value; + + public UTF8Info(ConstantPool pool) { + super(pool); + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getType() { + return type; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitUtf8Info(this); + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + ")]"; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + +} diff --git a/group15/1507_977996067/src/task7/jvm/field/Field.java b/group15/1507_977996067/src/task7/jvm/field/Field.java new file mode 100644 index 0000000000..989f3316c4 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/field/Field.java @@ -0,0 +1,48 @@ +package task7.jvm.field; + + +import task7.jvm.constant.ConstantPool; +import task7.jvm.constant.UTF8Info; +import task7.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.next2Bytes(); + int nameIndex = iter.next2Bytes(); + int descIndex = iter.next2Bytes(); + int attribCount = iter.next2Bytes(); + //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; + } + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/jvm/loader/ByteCodeIterator.java b/group15/1507_977996067/src/task7/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..81c268cdc9 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,56 @@ +package task7.jvm.loader; + +import task7.jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + + private int position; + + private byte[] bytes; + + public ByteCodeIterator(byte[] bytes) { + this.bytes = bytes; + } + + public String getMagicNumber() { + position = 0; + byte[] bytes = Arrays.copyOf(this.bytes, 4); + position += 4; + return Util.byteToHexString(bytes); + } + + public int next2Bytes() { + return nextBytes(2); + } + + public int next4Bytes() { + return nextBytes(4); + } + + public int nextFlag() { + return nextBytes(1); + } + + public void back(int length) { + position -= length; + } + + public byte[] getBytes(int length) { + byte[] bytes = Arrays.copyOfRange(this.bytes, position, position + length); + position += length; + return bytes; + } + + public String nextUxToHexString(int length) { + return new String(getBytes(length)); + } + + private int nextBytes(int size) { + byte[] bytes = Arrays.copyOfRange(this.bytes, position, position + size); + position += size; + return Util.byteToInt(bytes); + } + +} diff --git a/group15/1507_977996067/src/task7/jvm/loader/ClassFileLoader.java b/group15/1507_977996067/src/task7/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..350d8b92f4 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/loader/ClassFileLoader.java @@ -0,0 +1,122 @@ +package task7.jvm.loader; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import task7.jvm.clz.ClassFile; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) + ".class"; + + for (String path : this.clzPaths) { + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if (codes != null) { + return codes; + } + } + return null; + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + + public void addClassPath(String path) { + if (this.clzPaths.contains(path)) { + return; + } + + this.clzPaths.add(path); + + } + + + public String getClassPath() { + return StringUtils.join(this.clzPaths, ";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + // ------------------------------backup------------------------ + public String getClassPath_V1() { + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < this.clzPaths.size(); i++) { + buffer.append(this.clzPaths.get(i)); + if (i < this.clzPaths.size() - 1) { + buffer.append(";"); + } + } + return buffer.toString(); + } + + private byte[] loadClassFile_V1(String clzFileName) { + + BufferedInputStream bis = null; + + try { + + File f = new File(clzFileName); + + + bis = new BufferedInputStream(new FileInputStream(f)); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + + byte[] buffer = new byte[1024]; + int length = -1; + + while ((length = bis.read(buffer)) != -1) { + bos.write(buffer, 0, length); + } + + byte[] codes = bos.toByteArray(); + + return codes; + + } catch (IOException e) { + e.printStackTrace(); + + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + + } + + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/jvm/loader/ClassFileParser.java b/group15/1507_977996067/src/task7/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..eeea785114 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/loader/ClassFileParser.java @@ -0,0 +1,112 @@ +package task7.jvm.loader; + +import task7.jvm.clz.AccessFlag; +import task7.jvm.clz.ClassFile; +import task7.jvm.clz.ClassIndex; +import task7.jvm.constant.*; +import task7.jvm.field.Field; +import task7.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +public class ClassFileParser { + + private ConstantPool constantPool; + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(codes); + System.out.println(iterator.getMagicNumber()); + + classFile.setMinorVersion(iterator.next2Bytes()); + classFile.setMajorVersion(iterator.next2Bytes()); + + parseConstantPool(iterator); + classFile.setConstPool(constantPool); + classFile.setAccessFlag(parseAccessFlag(iterator)); + classFile.setClassIndex(parseClassIndex(iterator));//task5 over + + iterator.next2Bytes(); // interface + + classFile.setFields(parseFileds(iterator)); + classFile.setMethods(parseMethods(classFile, iterator));//task6 over + return classFile; + } + + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.next2Bytes()); + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex clazIndex = new ClassIndex(); + clazIndex.setThisClassIndex(iter.next2Bytes()); + clazIndex.setSuperClassIndex(iter.next2Bytes()); + return clazIndex; + } + + private void parseConstantPool(ByteCodeIterator iter) { + int poolCount = iter.next2Bytes(); + ConstantPool pool = new ConstantPool(poolCount); + for (int i = 0; i < poolCount; i++) { + int tag = iter.nextFlag(); + if (tag == ConstantInfo.UTF8_INFO) { //utf-8 + int length = iter.next2Bytes(); + byte[] bytes = iter.getBytes(length); + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setValue(new String(bytes)); + utf8Info.setLength(length); + pool.addConstantInfo(utf8Info); + } else if (tag == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.next2Bytes()); + pool.addConstantInfo(stringInfo); + } else if (tag == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.next2Bytes()); + pool.addConstantInfo(classInfo); + } else if (tag == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.next2Bytes()); + fieldRefInfo.setNameAndTypeIndex(iter.next2Bytes()); + pool.addConstantInfo(fieldRefInfo); + } else if (tag == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.next2Bytes()); + methodRefInfo.setNameAndTypeIndex(iter.next2Bytes()); + pool.addConstantInfo(methodRefInfo); + } else if (tag == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.next2Bytes()); + nameAndTypeInfo.setIndex2(iter.next2Bytes()); + pool.addConstantInfo(nameAndTypeInfo); + } + } + this.constantPool = pool; + } + + private List parseFileds(ByteCodeIterator iter) { + int fieldCount = iter.next2Bytes(); + + List fieldList = new ArrayList<>(fieldCount); + + for (int i = 0; i < fieldCount; i++) { + Field f = Field.parse(constantPool, iter); + fieldList.add(f); + } + return fieldList; + } + + private List parseMethods(ClassFile classFile, ByteCodeIterator iter) { + int methodCount = iter.next2Bytes(); + + List methodList = new ArrayList<>(methodCount); + + for (int i = 0; i < methodCount; i++) { + Method m = Method.parse(classFile, iter); + methodList.add(m); + } + return methodList; + } +} diff --git a/group15/1507_977996067/src/task7/jvm/method/Method.java b/group15/1507_977996067/src/task7/jvm/method/Method.java new file mode 100644 index 0000000000..13643df703 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/method/Method.java @@ -0,0 +1,91 @@ +package task7.jvm.method; + +import task7.jvm.attr.AttributeInfo; +import task7.jvm.attr.CodeAttr; +import task7.jvm.clz.ClassFile; +import task7.jvm.constant.ConstantPool; +import task7.jvm.constant.UTF8Info; +import task7.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.next2Bytes(); + int nameIndex = iter.next2Bytes(); + int descIndex = iter.next2Bytes(); + int attribCount = iter.next2Bytes(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for (int j = 1; j <= attribCount; j++) { + + int attrNameIndex = iter.next2Bytes(); + 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/group15/1507_977996067/src/task7/jvm/print/ClassFilePrinter.java b/group15/1507_977996067/src/task7/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..3f4607a044 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/print/ClassFilePrinter.java @@ -0,0 +1,44 @@ +package task7.jvm.print; + +import task7.jvm.clz.ClassFile; +import task7.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/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitor.java b/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitor.java new file mode 100644 index 0000000000..40851fc1bf --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitor.java @@ -0,0 +1,18 @@ +package task7.jvm.print; + +import task7.jvm.constant.*; + +public interface ConstantInfoVisitor { + + void visitClassInfo(ClassInfo classInfo); + + void visitFieldRefInfo(FieldRefInfo fieldRefInfo); + + void visitMethodRefInfo(MethodRefInfo methodRefInfo); + + void visitNameAndTypeInfo(NameAndTypeInfo nameAndTypeInfo); + + void visitStringInfo(StringInfo stringInfo); + + void visitUtf8Info(UTF8Info utf8Info); +} diff --git a/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitorImpl.java b/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitorImpl.java new file mode 100644 index 0000000000..776d23bc79 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/print/ConstantInfoVisitorImpl.java @@ -0,0 +1,51 @@ +package task7.jvm.print; + +import task7.jvm.constant.*; + +public class ConstantInfoVisitorImpl implements ConstantInfoVisitor { + @Override + public void visitClassInfo(ClassInfo classInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("Class\t#").append(classInfo.getUtf8Index()).append("\t").append(classInfo.getClassName()); + System.out.println(sb); + } + + @Override + public void visitFieldRefInfo(FieldRefInfo fieldRefInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("FieldRef\t#").append(fieldRefInfo.getClassInfoIndex()).append("\t").append(fieldRefInfo.getFieldName()); + System.out.println(sb); + + } + + @Override + public void visitMethodRefInfo(MethodRefInfo methodRefInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("MethodRef\t#").append(methodRefInfo.getMethodName()); + System.out.println(sb); + } + + @Override + public void visitNameAndTypeInfo(NameAndTypeInfo nameAndTypeInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("NameAndType\t#").append(nameAndTypeInfo.getName()).append("\t") + .append(nameAndTypeInfo.getIndex1()).append("\t") + .append(nameAndTypeInfo.getIndex2()).append("\t") + .append(nameAndTypeInfo.getTypeInfo()); + System.out.println(sb); + } + + @Override + public void visitStringInfo(StringInfo stringInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("String\t#").append(stringInfo.getIndex()); + System.out.println(sb); + } + + @Override + public void visitUtf8Info(UTF8Info utf8Info) { + StringBuilder sb = new StringBuilder(); + sb.append("UTF8\t#").append(utf8Info.getValue()); + System.out.println(sb); + } +} diff --git a/group15/1507_977996067/src/task7/jvm/print/ConstantPoolPrinter.java b/group15/1507_977996067/src/task7/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..d6e87cad83 --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,26 @@ +package task7.jvm.print; + +import task7.jvm.constant.ConstantInfo; +import task7.jvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + + private ConstantPool pool; + + ConstantPoolPrinter(ConstantPool pool) { + this.pool = pool; + } + + public void print() { + + System.out.println("Constant Pool:"); + + ConstantInfoVisitor visitor = new ConstantInfoVisitorImpl(); + int size = (int) pool.getSize(); + for (int i = 0; i < size; i++) { + System.out.print("#" + i + "= "); + ConstantInfo constantInfo = pool.getConstantInfo(i); + constantInfo.accept(visitor); + } + } +} diff --git a/group15/1507_977996067/src/task7/jvm/test/ClassFileloaderTest.java b/group15/1507_977996067/src/task7/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..53bea9b04e --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,191 @@ +package task7.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import task7.jvm.clz.ClassFile; +import task7.jvm.clz.ClassIndex; +import task7.jvm.constant.*; +import task7.jvm.loader.ClassFileLoader; + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "EmployeeV1"; + + static String path1 = "E:\\Idea\\coding2017\\group15\\1507_977996067\\out\\task5\\jvm\\test"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "EmployeeV1"; + + clzFile = loader.loadClass(className); +// clzFile.print(); + } + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1038, byteCodes.length); + + } + + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + String actualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", actualValue); + } + + + private String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } + + /** + * ---------------------------------------------------------------------- + */ + + + @Test + public void testVersion() { + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool() { + + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + + @Test + public void testClassIndex() { + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + +} diff --git a/group15/1507_977996067/src/task7/jvm/test/EmployeeV1.java b/group15/1507_977996067/src/task7/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..866b94811a --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +package task7.jvm.test; + +public class EmployeeV1 { + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age; + } + + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + + public static void main(String[] args) { + EmployeeV1 p = new EmployeeV1("Andy", 29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task7/jvm/util/Util.java b/group15/1507_977996067/src/task7/jvm/util/Util.java new file mode 100644 index 0000000000..60158ac03a --- /dev/null +++ b/group15/1507_977996067/src/task7/jvm/util/Util.java @@ -0,0 +1,23 @@ +package task7.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16); + } + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i Date: Sun, 23 Apr 2017 15:46:09 +0800 Subject: [PATCH 105/151] =?UTF-8?q?=E5=AE=8C=E6=88=904=E6=9C=8816=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../785396327/4.9/expr/InfixToPostfix.java | 34 ++++++++++++++- .../4.9/expr/InfixToPostfixTest.java | 41 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 group17/785396327/4.9/expr/InfixToPostfixTest.java diff --git a/group17/785396327/4.9/expr/InfixToPostfix.java b/group17/785396327/4.9/expr/InfixToPostfix.java index 720be5b28a..58fb60ef2b 100644 --- a/group17/785396327/4.9/expr/InfixToPostfix.java +++ b/group17/785396327/4.9/expr/InfixToPostfix.java @@ -1,13 +1,43 @@ package expr; +import stack.MyStack; + +import java.util.ArrayList; import java.util.List; /** * Created by gongxun on 2017/4/22. + * 遇到数组直接放入集合等待输出 + * 遇到运算符入栈,如果栈顶元素的优先级较待入栈运算符的优先级高,将栈顶元素取出放入集合等待输出,否则直接入栈 */ public class InfixToPostfix { public static List convert(String expr) { - - return null; + List result = new ArrayList(); + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + MyStack stack = new MyStack(); + if (tokens != null) { + for (Token token : tokens) { + if (token.isNumber()) + result.add(token); + else { + while (!stack.isEmpty()) { + Token prevOper = stack.peek(); + if (token.hasHigherPriority(prevOper)) { + stack.push(token); + break; + } else { + result.add(stack.pop()); + } + } + //和+或者-同优先级或者更高优先级的都已经弹栈,只剩空栈 + if (stack.isEmpty()) stack.push(token); + } + } + } + //将剩余的所有符号出栈 + while (!stack.isEmpty()) + result.add(stack.pop()); + return result; } } diff --git a/group17/785396327/4.9/expr/InfixToPostfixTest.java b/group17/785396327/4.9/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..f1dcd3f466 --- /dev/null +++ b/group17/785396327/4.9/expr/InfixToPostfixTest.java @@ -0,0 +1,41 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by IBM on 2017/4/23. + */ +public class InfixToPostfixTest { + + + @Before + public void setUp() { + + } + + @After + public void tearDown() { + + } + + @Test + public void testConvert() { + { + Assert.assertEquals("[2, 3, 4, *, +, 5, +]", InfixToPostfix.convert("2+3*4+5").toString()); + } + { + Assert.assertEquals("[3, 20, *, 12, 5, *, +, 40, 2, /, -]", InfixToPostfix.convert("3*20+12*5-40/2").toString()); + } + + { + Assert.assertEquals("[3, 20, *, 2, /]", InfixToPostfix.convert("3*20/2").toString()); + } + + { + Assert.assertEquals("[20, 2, /, 3, *]", InfixToPostfix.convert("20/2*3").toString()); + } + } +} From e4d42eb61f08dd8141394547ff9e7b515d7002f1 Mon Sep 17 00:00:00 2001 From: RalfNick Date: Sun, 23 Apr 2017 15:58:31 +0800 Subject: [PATCH 106/151] Only data struct --- .../data-struct/com/ralf/stack/MyStack.java" | 42 +++++ .../com/ralf/stack/StackUtil.java" | 173 ++++++++++++++++++ .../com/ralf/stack/StackUtilsTest.java" | 87 +++++++++ .../com/ralf/stack/expr/ExprIterator.java" | 57 ++++++ .../com/ralf/stack/expr/InfixExpr.java" | 74 ++++++++ .../com/ralf/stack/expr/InfixExprTest.java" | 44 +++++ .../com/ralf/stack/expr/InfixToPostExpr.java" | 41 +++++ .../ralf/stack/expr/InfixToPostExprTest.java" | 30 +++ .../com/ralf/stack/expr/PostfixExpr.java" | 48 +++++ .../com/ralf/stack/expr/PostfixExprTest.java" | 34 ++++ .../com/ralf/stack/expr/PrefixExpr.java" | 59 ++++++ .../com/ralf/stack/expr/PrefixExprTest.java" | 39 ++++ .../com/ralf/stack/expr/Token.java" | 49 +++++ .../com/ralf/stack/expr/TokenParser.java" | 56 ++++++ .../com/ralf/stack/expr/TokenParserTest.java" | 36 ++++ 15 files changed, 869 insertions(+) create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExpr.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExprTest.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExpr.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExprTest.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExpr.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExprTest.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/Token.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParser.java" create mode 100644 "group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParserTest.java" diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" new file mode 100644 index 0000000000..147ee9e15f --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" @@ -0,0 +1,42 @@ +package com.ralf.stack; + +import java.util.LinkedList; +import java.util.NoSuchElementException; + +/** + * ʵ�ֻ������ݽṹջ + * + * @author Ralf + * + */ +public class MyStack { + + private LinkedList linkedList = new LinkedList<>(); + + public MyStack() { + + } + + public void push(T t) { + linkedList.addFirst(t); + } + + public T pop() { + if (size() == 0) { + throw new NoSuchElementException(); + } + return linkedList.removeFirst(); + } + + public T peek() { + return (size() == 0) ? null : linkedList.getFirst(); + } + + public int size() { + return linkedList.size(); + } + + public boolean isEmpty(){ + return linkedList.isEmpty(); + } +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" new file mode 100644 index 0000000000..758178131c --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" @@ -0,0 +1,173 @@ +package com.ralf.stack; + +import java.util.NoSuchElementException; + +public class StackUtil { + + private static MyStack myStack = new MyStack<>(); + + /** + * ����ջ�е�Ԫ����Integer, ��ջ����ջ���� : 5,4,3,2,1 ���ø÷����� Ԫ�ش����Ϊ: 1,2,3,4,5 + * ע�⣺ֻ��ʹ��Stack�Ļ�����������push,pop,peek,isEmpty�� ����ʹ������һ��ջ������ + * + * @param + */ + public static void reverse(MyStack stack) { + + if (stack.isEmpty()) { + System.out.println("��ջΪ��ջ��"); + return; + } + @SuppressWarnings("unchecked") + T[] elements = (T[]) new Object[stack.size()]; + for (int i = 0; i < elements.length; i++) { + elements[i] = stack.pop(); + } + for (int i = 0; i < elements.length; i++) { + stack.push(elements[i]); + } + + } + + public static void bad_reverse(MyStack s) { + if(s == null || s.isEmpty()){ + return; + } + MyStack tmpStack = new MyStack<>(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + + /** + * ɾ��ջ�е�ij��Ԫ�� ע�⣺ֻ��ʹ��Stack�Ļ�����������push,pop,peek,isEmpty�� ����ʹ������һ��ջ������ + * + * @param o + */ + public static void remove(MyStack s, T o) { + if (s.isEmpty()) { + System.out.println("��ջΪ�գ�"); + return; + } + MyStack stack = new MyStack<>(); + + while (!s.isEmpty()) { + T t = s.pop(); + if (t.equals(o)) { + PopAndPush(s, stack); + return; + } + stack.push(t); + } + throw new NoSuchElementException("��ջû�и�Ԫ�أ�"); + + } + + private static void PopAndPush(MyStack s, MyStack stack) { + while (!stack.isEmpty()) { + T t = stack.pop(); + s.push(t); + } + } + + /** + * ��ջ��ȡ��len��Ԫ��, ԭ����ջ��Ԫ�ر��ֲ��� ע�⣺ֻ��ʹ��Stack�Ļ�����������push,pop,peek,isEmpty�� + * ����ʹ������һ��ջ������ + * + * @param len + * @return + */ + @SuppressWarnings("unchecked") + public static T[] getTop(MyStack s, int len) { + + if (s.isEmpty() || len > s.size()) { + return null; + } + MyStack oldStack = s; + T[] elements = (T[]) new Object[len]; + for (int i = 0; i < len; i++) { + elements[i] = s.pop(); + } + s = oldStack; + return elements; + } + + /** + * �ַ���s ���ܰ�����Щ�ַ��� ( ) [ ] { }, a,b,c... x,yz ʹ�ö�ջ����ַ���s�е������Dz��dzɶԳ��ֵġ� ����s = + * "([e{d}f])" , ����ַ����е������dzɶԳ��֣� �÷�������true ��� s = "([b{x]y})", + * ����ַ����е����Ų��dzɶԳ��ֵģ� �÷�������false; + * + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + + char[] ch = s.toCharArray(); + if (ch.length < 1) { + return false; + } + + MyStack leftStack = new MyStack<>(); + MyStack rightStack = new MyStack<>(); + + for (int i = 0; i < ch.length; i++) { + + switch (ch[i]) { + case '(': + leftStack.push(String.valueOf(ch[i])); + break; + + case '[': + leftStack.push(String.valueOf(ch[i])); + break; + + case '{': + leftStack.push(String.valueOf(ch[i])); + break; + + case ')': + rightStack.push(String.valueOf(ch[i])); + break; + + case ']': + rightStack.push(String.valueOf(ch[i])); + break; + + case '}': + rightStack.push(String.valueOf(ch[i])); + break; + + default: + break; + } + } + return isPair(leftStack, rightStack); + + } + + private static boolean isPair(MyStack leftStack, + MyStack rightStack) { + + if (leftStack.size() != rightStack.size()) { + return false; + } + + reverse(rightStack); + while (!leftStack.isEmpty()) { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(leftStack.pop()).append(rightStack.pop()); + + String pair = stringBuilder.toString(); + if (!pair.equals("()") && !pair.equals("[]") && !pair.equals("{}")) { + return false; + } + } + return true; + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" new file mode 100644 index 0000000000..f547c5e0c1 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" @@ -0,0 +1,87 @@ +package com.ralf.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class StackUtilsTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testReverse() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.reverse(stack); + //Assert.assertEquals(5, stack.size()); + + Assert.assertEquals(1, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(3, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(5, stack.pop().intValue()); + } + + @Test + public void testRemove() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.remove(stack, 3); + + Assert.assertEquals(4, stack.size()); + + Assert.assertEquals(5, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(1, stack.pop().intValue()); + } + + public void testGetTop() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + Integer[] integerReal = StackUtil.getTop(stack, 3); + int[] intExpeted = { 1, 2, 3 }; + int[] intReal = new int[integerReal.length]; + for (int i = 0; i < integerReal.length; i++) { + intReal[i] = integerReal[i]; + } + Assert.assertEquals(5, stack.size()); + Assert.assertArrayEquals(intExpeted, intReal); + + } + + @Test + public void testIsValidPair(){ + + String stringTrue = "([e{d}f])"; + String stringFalse = "([b{x]y})"; + + Assert.assertTrue(StackUtil.isValidPairs(stringTrue)); + Assert.assertFalse(StackUtil.isValidPairs(stringFalse)); + + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" new file mode 100644 index 0000000000..d82db3e915 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" @@ -0,0 +1,57 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; + +public class ExprIterator { + + private int operPos; + private int numPos; + private ArrayList operateList = new ArrayList<>(); + private ArrayList numList = new ArrayList<>(); + + public ExprIterator(String exprString) { + char[] chs = exprString.toCharArray(); + transToString(chs); + } + + public Integer nextNumString() { + if (hasNextNum()) { + return Integer.parseInt(numList.get(numPos++)); + } + return null; + } + public String nextOperateString() { + if (hasNextOperate()) { + return operateList.get(operPos++); + } + return null; + } + + public boolean hasNextNum() { + return numPos < numList.size(); + } + + public boolean hasNextOperate() { + return operPos < operateList.size(); + } + + private void transToString(char[] chs) { + + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < chs.length; i++) { + if (chs[i] == '+' || chs[i] == '-' || chs[i] == '*' + || chs[i] == '/') { + numList.add(stringBuilder.toString()); + operateList.add(String.valueOf(chs[i])); + stringBuilder.delete(0, stringBuilder.length()); + } + else { + stringBuilder.append(chs[i]); + } + + } + numList.add(stringBuilder.toString()); + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" new file mode 100644 index 0000000000..86a060845c --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" @@ -0,0 +1,74 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class InfixExpr { + + private String exprString; + + public InfixExpr(String exprString) { + this.exprString = exprString; + } + + public double evaluate() { + + MyStack numStack = new MyStack(); + MyStack operStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + + List list = parser.parse(exprString); + + for (Token token : list) { + if (token.isOperator()) { + if (operStack.isEmpty()) { + operStack.push(token); + } else { + while (!operStack.isEmpty() + && !token.hasHigherPriority(operStack.peek())) { + String operator = operStack.pop().toString(); + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = operate(operator,num1,num2); + numStack.push(result); + } + operStack.push(token); + } + } + if (token.isNumber()) { + numStack.push(new Float(token.getValue())); + } + } + + while(!operStack.isEmpty()){ + String operator = operStack.pop().toString(); + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = operate(operator,num1,num2); + numStack.push(result); + } + + return numStack.pop().floatValue(); + } + + private Float operate(String operator,Float num1, Float num2) { + float result = 0.0f; + switch (operator) { + case "+": + result = num2 + num1; + break; + case "-": + result = num2 - num1; + break; + case "*": + result = num2 * num1; + break; + case "/": + result = num2 / num1; + break; + } + return result; + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" new file mode 100644 index 0000000000..cd987b94b0 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" @@ -0,0 +1,44 @@ +package com.ralf.stack.expr; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExpr.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExpr.java" new file mode 100644 index 0000000000..6296d160ef --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExpr.java" @@ -0,0 +1,41 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +import com.ralf.stack.MyStack; +import com.ralf.stack.StackUtil; + +public class InfixToPostExpr { + + public static List convert(String infixString){ + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(infixString); + + MyStack S1 = new MyStack(); + MyStack S2 = new MyStack<>(); + + + for(Token token : tokens){ + if (token.isNumber()) { + S2.push(token); + } + else{ + while(!S1.isEmpty() && !token.hasHigherPriority(S1.peek())) { + S2.push(S1.pop()); + } + S1.push(token); + } + } + while(!S1.isEmpty()){ + S2.push(S1.pop()); + } + ArrayList list = new ArrayList<>(); + StackUtil.reverse(S2); + while(!S2.isEmpty()){ + list.add(S2.pop()); + } + return list; + } +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExprTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExprTest.java" new file mode 100644 index 0000000000..d21344ea1e --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixToPostExprTest.java" @@ -0,0 +1,30 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixToPostExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + //10-2*3+50 + String string = "10-2*3+50"; + List tokens = InfixToPostExpr.convert(string); + + Assert.assertEquals(10, tokens.get(0).getValue()); + Assert.assertEquals(2, tokens.get(1).getValue()); + Assert.assertEquals(3, tokens.get(2).getValue()); + Assert.assertEquals("*", tokens.get(3).toString()); + Assert.assertEquals("-", tokens.get(4).toString()); + Assert.assertEquals(50, tokens.get(5).getValue()); + Assert.assertEquals("+", tokens.get(6).toString()); + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExpr.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExpr.java" new file mode 100644 index 0000000000..6e40dbe72f --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExpr.java" @@ -0,0 +1,48 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class PostfixExpr { + + private String exprString; + + public PostfixExpr(String exprString){ + this.exprString = exprString; + } + + public float evaluate() { + MyStack myStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(exprString); + for(Token token : tokens){ + if (token.isNumber()) { + myStack.push(new Float(token.getValue())); + } + if (token.isOperator()) { + float f2 = myStack.pop(); + float f1 = myStack.pop(); + myStack.push(calculate(token.toString(), f1, f2)); + } + } + return myStack.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"); + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExprTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExprTest.java" new file mode 100644 index 0000000000..d5ff875c0f --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PostfixExprTest.java" @@ -0,0 +1,34 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + { + 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/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExpr.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExpr.java" new file mode 100644 index 0000000000..651889259e --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExpr.java" @@ -0,0 +1,59 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class PrefixExpr { + + private String exprString; + + public PrefixExpr(String exprString) { + this.exprString = exprString; + } + + public float evaluate() { + + MyStack myStack = new MyStack<>(); + MyStack exprStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(exprString); + + for(Token token : tokens){ + exprStack.push(token); + } + + while(!exprStack.isEmpty()){ + Token token = exprStack.pop(); + if (token.isNumber()) { + myStack.push(new Float(token.getValue())); + } + else { + Float f1 = myStack.pop(); + Float f2 = myStack.pop(); + myStack.push(calculate(token.toString(),f1,f2)); + } + } + return myStack.pop().floatValue(); + } + + private Float calculate(String operator, Float f1, Float f2) { + if ("+".equals(operator)) { + return f1 + f2; + } + if ("-".equals(operator)) { + return f1 - f2; + } + if ("*".equals(operator)) { + return f1 * f2; + } + if ("/".equals(operator)) { + return f1 / f2; + } + else { + throw new RuntimeException("this operator is not supported!"); + } + + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExprTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExprTest.java" new file mode 100644 index 0000000000..ff11cc2395 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/PrefixExprTest.java" @@ -0,0 +1,39 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + { + // 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/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/Token.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/Token.java" new file mode 100644 index 0000000000..1696dafbef --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/Token.java" @@ -0,0 +1,49 @@ +package com.ralf.stack.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public 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 NUMBER = 1; + static final int OPERATOR = 2; + String value; + int type; + + public Token(String value, int type){ + this.value = value; + this.type = type; + } + public int getValue() { + + return Integer.valueOf(value).intValue(); + } + public String toString(){ + return value; + } + public boolean isNumber(){ + return type == NUMBER; + } + public boolean isOperator(){ + return type == OPERATOR; + } + public boolean hasHigherPriority(Token token){ + + if (!this.isOperator() || !token.isOperator()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(token.value) > 0; + + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParser.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParser.java" new file mode 100644 index 0000000000..66206c9f11 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParser.java" @@ -0,0 +1,56 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + public TokenParser(){ + + } + public List parse(String string) { + List tokens = new ArrayList(); + int i = 0; + while(i < string.length()){ + + char ch = string.charAt(i); + if (isOperator(ch)) { + Token token = new Token(String.valueOf(ch), Token.OPERATOR); + tokens.add(token); + i++; + } + else if (Character.isDigit(ch)) { + int nextIndexOfChar = nextIndexOfOperator(i,string); + String value = string.substring(i, nextIndexOfChar); + Token token = new Token(value, Token.NUMBER); + tokens.add(token); + i = nextIndexOfChar; + } + else { + System.out.println("char:" + ch + " is not a number or operator,ignore!"); + i++; + } + + } + + + return tokens; + } + + private int nextIndexOfOperator(int i, String string) { + + while(Character.isDigit(string.charAt(i))){ + i++; + if (i == string.length()) { + break; + } + } + return i; + } + + private boolean isOperator(char ch) { + String string = String.valueOf(ch); + return Token.OPERATORS.contains(string); + } + +} diff --git "a/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParserTest.java" "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParserTest.java" new file mode 100644 index 0000000000..3066880551 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\270\203\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/TokenParserTest.java" @@ -0,0 +1,36 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TokenParserTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + TokenParser tokenParser = new TokenParser(); + + List list = tokenParser.parse("300*20+12*5-20/4"); + Assert.assertEquals(300, list.get(0).getValue()); + Assert.assertEquals("*", list.get(1).toString()); + Assert.assertEquals(20, list.get(2).getValue()); + Assert.assertEquals("+", list.get(3).toString()); + Assert.assertEquals(12, list.get(4).getValue()); + Assert.assertEquals("*", list.get(5).toString()); + Assert.assertEquals(5, list.get(6).getValue()); + Assert.assertEquals("-", list.get(7).toString()); + Assert.assertEquals(20, list.get(8).getValue()); + Assert.assertEquals("/", list.get(9).toString()); + Assert.assertEquals(4, list.get(10).getValue()); + + } + +} From d6e495d4434e0074d98e2ee060e1acff6cf0d640 Mon Sep 17 00:00:00 2001 From: sheng <1158154002@qq.com> Date: Sun, 23 Apr 2017 17:13:06 +0800 Subject: [PATCH 107/151] test07 --- .../src/test05/stack/StackTest.java | 2 +- .../src/test05/stack/StackUtil.java | 12 ++-- .../src/test07/expr/InfixToPostfix.java | 56 +++++++++++++++++++ .../src/test07/expr/InfixToPostfixTest.java | 12 ++++ .../src/test07/expr/PostfixExpr.java | 48 ++++++++++++++++ .../src/test07/expr/PostfixExprTest.java | 36 ++++++++++++ .../src/test07/expr/PrefixExpr.java | 49 ++++++++++++++++ .../src/test07/expr/PrefixExprTest.java | 43 ++++++++++++++ group17/1158154002/src/test07/expr/Token.java | 54 ++++++++++++++++++ .../src/test07/expr/TokenParser.java | 55 ++++++++++++++++++ .../src/test07/expr/TokenParserTest.java | 37 ++++++++++++ 11 files changed, 398 insertions(+), 6 deletions(-) create mode 100644 group17/1158154002/src/test07/expr/InfixToPostfix.java create mode 100644 group17/1158154002/src/test07/expr/InfixToPostfixTest.java create mode 100644 group17/1158154002/src/test07/expr/PostfixExpr.java create mode 100644 group17/1158154002/src/test07/expr/PostfixExprTest.java create mode 100644 group17/1158154002/src/test07/expr/PrefixExpr.java create mode 100644 group17/1158154002/src/test07/expr/PrefixExprTest.java create mode 100644 group17/1158154002/src/test07/expr/Token.java create mode 100644 group17/1158154002/src/test07/expr/TokenParser.java create mode 100644 group17/1158154002/src/test07/expr/TokenParserTest.java diff --git a/group17/1158154002/src/test05/stack/StackTest.java b/group17/1158154002/src/test05/stack/StackTest.java index b311650fff..a5d6b39344 100644 --- a/group17/1158154002/src/test05/stack/StackTest.java +++ b/group17/1158154002/src/test05/stack/StackTest.java @@ -7,7 +7,7 @@ public class StackTest { @Test public void testReverse(){ - Stack stack=new Stack(); + Stack stack=new Stack(); stack.push(1); stack.push(2); stack.push(3); diff --git a/group17/1158154002/src/test05/stack/StackUtil.java b/group17/1158154002/src/test05/stack/StackUtil.java index ead00078b6..2904bec41c 100644 --- a/group17/1158154002/src/test05/stack/StackUtil.java +++ b/group17/1158154002/src/test05/stack/StackUtil.java @@ -1,16 +1,19 @@ package test05.stack; + + public class StackUtil { /** - * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 假设栈中的元素是T, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param */ - public static void reverse(Stack s) { - Stack temp=new Stack(); + public static void reverse(Stack s) { + Stack temp=new Stack(); while (s.peek()!=null) { temp.push(s.pop()); } - Stack temp2=new Stack(); + Stack temp2=new Stack(); while (temp.peek()!=null) { temp2.push(temp.pop()); } @@ -145,5 +148,4 @@ public static boolean isValidPairs(String s){ return stack.size() == 0; } - } diff --git a/group17/1158154002/src/test07/expr/InfixToPostfix.java b/group17/1158154002/src/test07/expr/InfixToPostfix.java new file mode 100644 index 0000000000..e88f211eb8 --- /dev/null +++ b/group17/1158154002/src/test07/expr/InfixToPostfix.java @@ -0,0 +1,56 @@ +package test07.expr; + +import java.util.ArrayList; +import java.util.List; + +import test05.stack.Stack; + +public class InfixToPostfix { + // 2+3*4-8/2 2 3 4 * + 8 2 / - + // 2+3*4-8/2+3 + // 2+3*4*5*5-8/2 2 3 4 * 5 * 5 * + 8 2 / - + // 2+3*4*5*5-8/2/2 2 3 4 * 5 * 5 * + 8 2 / - + public static List convert(String expr) { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + List result = new ArrayList(); + + Stack opStack = new Stack<>(); + for (Token token : tokens) { + + if (token.isOperator()) { + + if (opStack.isEmpty()) { + opStack.push(token); + } else { + + if (token.hasHigherPriority()&&!opStack.peek().hasHigherPriority()) { + opStack.push(token); + } else if (!token.hasHigherPriority()&&opStack.peek().hasHigherPriority()) { + if (opStack.size() > 1) { + while (opStack.size() > 0) { + result.add(opStack.pop()); + } + } + opStack.push(token); + } + else { + result.add(token); + } + } + } + if (token.isNumber()) { + result.add(token); + } + } + while (opStack.size() > 0) { + result.add(opStack.pop()); + } + for (Token token : result) { + System.out.print(token.value + " "); + } + System.out.println(); + return result; + } +} diff --git a/group17/1158154002/src/test07/expr/InfixToPostfixTest.java b/group17/1158154002/src/test07/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..eb11aae32d --- /dev/null +++ b/group17/1158154002/src/test07/expr/InfixToPostfixTest.java @@ -0,0 +1,12 @@ +package test07.expr; + +public class InfixToPostfixTest { + + public static void main(String[] args) { + //2+3*4-8/2 + //2+3*4*5*5-8/2 + InfixToPostfix.convert("2+3*4*5*5-8/2/2"); + InfixToPostfix.convert("2+3"); + } + +} diff --git a/group17/1158154002/src/test07/expr/PostfixExpr.java b/group17/1158154002/src/test07/expr/PostfixExpr.java new file mode 100644 index 0000000000..5e4e35433c --- /dev/null +++ b/group17/1158154002/src/test07/expr/PostfixExpr.java @@ -0,0 +1,48 @@ +package test07.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() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + Float f2=numStack.pop(); + Float f1=numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + 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"); + } +} diff --git a/group17/1158154002/src/test07/expr/PostfixExprTest.java b/group17/1158154002/src/test07/expr/PostfixExprTest.java new file mode 100644 index 0000000000..11e17fc804 --- /dev/null +++ b/group17/1158154002/src/test07/expr/PostfixExprTest.java @@ -0,0 +1,36 @@ +package test07.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/group17/1158154002/src/test07/expr/PrefixExpr.java b/group17/1158154002/src/test07/expr/PrefixExpr.java new file mode 100644 index 0000000000..c02253ab1c --- /dev/null +++ b/group17/1158154002/src/test07/expr/PrefixExpr.java @@ -0,0 +1,49 @@ +package test07.expr; + +import java.util.List; +import java.util.Stack; + +import test05.stack.StackUtil; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack numStack = new Stack<>(); + + for (int i = tokens.size()-1; i >=0; i--) { + Token token=tokens.get(i); + if (token.isOperator()){ + Float f2=numStack.pop(); + Float f1=numStack.pop(); + numStack.push(calculate(token.toString(), f2, f1)); + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + 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"); + } +} diff --git a/group17/1158154002/src/test07/expr/PrefixExprTest.java b/group17/1158154002/src/test07/expr/PrefixExprTest.java new file mode 100644 index 0000000000..04ed04ad0a --- /dev/null +++ b/group17/1158154002/src/test07/expr/PrefixExprTest.java @@ -0,0 +1,43 @@ +package test07.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/group17/1158154002/src/test07/expr/Token.java b/group17/1158154002/src/test07/expr/Token.java new file mode 100644 index 0000000000..7cd540bb3d --- /dev/null +++ b/group17/1158154002/src/test07/expr/Token.java @@ -0,0 +1,54 @@ +package test07.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public 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 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; + } + + public boolean hasHigherPriority(){ + if(!this.isOperator()){ + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) -1 > 0; + } +} diff --git a/group17/1158154002/src/test07/expr/TokenParser.java b/group17/1158154002/src/test07/expr/TokenParser.java new file mode 100644 index 0000000000..7e3a4db91b --- /dev/null +++ b/group17/1158154002/src/test07/expr/TokenParser.java @@ -0,0 +1,55 @@ +package test07.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/group17/1158154002/src/test07/expr/TokenParserTest.java b/group17/1158154002/src/test07/expr/TokenParserTest.java new file mode 100644 index 0000000000..926a03e70e --- /dev/null +++ b/group17/1158154002/src/test07/expr/TokenParserTest.java @@ -0,0 +1,37 @@ +package test07.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()); + } +} From ae3aef5cd6df307c302950dc81a4c73d9b5ad3a0 Mon Sep 17 00:00:00 2001 From: lzb Date: Sun, 23 Apr 2017 17:56:46 +0800 Subject: [PATCH 108/151] =?UTF-8?q?jvm=E7=AC=AC=E5=9B=9B=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/me/lzb/basic/InfixExpr.java | 161 --------------- .../main/java/me/lzb/basic/expr/CalUtil.java | 108 ++++++++++ .../java/me/lzb/basic/expr/InfixExpr.java | 71 +++++++ .../me/lzb/basic/expr/InfixToPostfix.java | 79 ++++++++ .../src/main/java/me/lzb/basic/expr/Node.java | 28 +++ .../java/me/lzb/basic/expr/PostfixExpr.java | 46 +++++ .../java/me/lzb/basic/expr/PrefixExpr.java | 46 +++++ .../lzb/basic/{ => expr}/InfixExprTest.java | 2 +- .../me/lzb/basic/expr/InfixToPostfixTest.java | 42 ++++ .../me/lzb/basic/expr/PostfixExprTest.java | 43 ++++ .../me/lzb/basic/expr/PrefixExprTest.java | 47 +++++ .../main/java/me/lzb/jvm/attr/CodeAttr.java | 13 +- .../main/java/me/lzb/jvm/clz/AccessFlag.java | 12 +- .../main/java/me/lzb/jvm/clz/ClassFile.java | 59 ++++-- .../main/java/me/lzb/jvm/cmd/BiPushCmd.java | 21 ++ .../java/me/lzb/jvm/cmd/ByteCodeCommand.java | 124 ++++++++++++ .../main/java/me/lzb/jvm/cmd/GetFieldCmd.java | 20 ++ .../me/lzb/jvm/cmd/GetStaticFieldCmd.java | 19 ++ .../java/me/lzb/jvm/cmd/InvokeSpecialCmd.java | 21 ++ .../java/me/lzb/jvm/cmd/InvokeVirtualCmd.java | 19 ++ .../src/main/java/me/lzb/jvm/cmd/LdcCmd.java | 29 +++ .../java/me/lzb/jvm/cmd/NewObjectCmd.java | 19 ++ .../java/me/lzb/jvm/cmd/NoOperandCmd.java | 22 ++ .../java/me/lzb/jvm/cmd/OneOperandCmd.java | 29 +++ .../main/java/me/lzb/jvm/cmd/PutFieldCmd.java | 20 ++ .../java/me/lzb/jvm/cmd/TwoOperandCmd.java | 64 ++++++ .../java/me/lzb/jvm/constant/ClassInfo.java | 7 + .../me/lzb/jvm/constant/ConstantInfo.java | 16 +- .../me/lzb/jvm/constant/FieldRefInfo.java | 7 + .../me/lzb/jvm/constant/MethodRefInfo.java | 7 + .../me/lzb/jvm/constant/NameAndTypeInfo.java | 7 + .../me/lzb/jvm/constant/NullConstantInfo.java | 7 + .../java/me/lzb/jvm/constant/StringInfo.java | 7 + .../java/me/lzb/jvm/constant/UTF8Info.java | 7 + .../me/lzb/jvm/loader/ClassFileParser.java | 8 +- .../java/me/lzb/jvm/loader/CommandParser.java | 188 ++++++++++++++++++ .../main/java/me/lzb/jvm/method/Method.java | 26 ++- .../java/me/lzb/jvm/print/ClassPrinter.java | 36 ++++ .../src/main/java/me/lzb/jvm/print/Print.java | 10 + .../java/me/lzb/jvm/print/PrintFormat.java | 57 ++++++ .../java/me/lzb/jvm/print/PrintVisitor.java | 23 +++ .../java/me/lzb/jvm/ClassFileloaderTest.java | 95 ++++++++- 42 files changed, 1472 insertions(+), 200 deletions(-) delete mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/CalUtil.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixExpr.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixToPostfix.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/Node.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PostfixExpr.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PrefixExpr.java rename group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/{ => expr}/InfixExprTest.java (97%) create mode 100644 group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixToPostfixTest.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PostfixExprTest.java create mode 100644 group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PrefixExprTest.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/Print.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java create mode 100644 group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java deleted file mode 100644 index e30cc00cc2..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java +++ /dev/null @@ -1,161 +0,0 @@ -package me.lzb.basic; - -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; - -/** - * Created by LZB on 2017/4/15. - */ -public class InfixExpr { - - - private String expr; - - public InfixExpr(String expr) { - this.expr = expr; - } - - public float evaluate() { - - List list = processExpr(); - - Stack symbolStack = new Stack<>(); - Stack numberStack = new Stack<>(); - - boolean calLevel2 = false; - for (Node n : list) { - if (n.isNumber) { - numberStack.push(n.number); - if (calLevel2) { - calculate(symbolStack, numberStack, false); - calLevel2 = false; - } - } else { - symbolStack.push(n.symbol); - - if (n.isLevel2()) { - calLevel2 = true; - } - } - } - - - Stack tn = new Stack<>(); - int nsize = numberStack.size(); - for (int i = 0; i < nsize; i++) { - tn.push(numberStack.pop()); - } - - numberStack = tn; - - - Stack ts = new Stack<>(); - int ssize = symbolStack.size(); - for (int i = 0; i < ssize; i++) { - ts.push(symbolStack.pop()); - } - - symbolStack = ts; - - - while (!symbolStack.isEmpty()) { - calculate(symbolStack, numberStack, true); - } - - - return numberStack.pop(); - } - - - - private List processExpr() { - List list = new ArrayList<>(); - char[] array = this.expr.toCharArray(); - String number = ""; - for (int i = 0; i < array.length; i++) { - if (Character.isDigit(array[i])) { - number = number + String.valueOf(array[i]); - } else { - Node num = new Node(Float.valueOf(number), null, true, -1); - number = ""; - int calLevel = "+-".indexOf(array[i]) >= 0 ? 1 : 2; - Node sym = new Node(0, String.valueOf(array[i]), false, calLevel); - list.add(num); - list.add(sym); - } - } - - Node num = new Node(Float.valueOf(number), null, true, -1); - list.add(num); - return list; - } - - - private void calculate(Stack symbolStack, Stack numberStack, boolean isRe) { - if (symbolStack.isEmpty()) { - return; - } - - - String symbole = symbolStack.pop(); - - float right; - float left; - - if(isRe){ - left = numberStack.pop(); - right = numberStack.pop(); - }else { - right = numberStack.pop(); - left = numberStack.pop(); - } - - - - float r = calculate(symbole, left, right); - - numberStack.push(r); - } - - - private float calculate(String symbol, float left, float right) { - if ("+".equals(symbol)) { - return left + right; - } - - if ("-".equals(symbol)) { - return left - right; - } - - if ("*".equals(symbol)) { - return left * right; - } - - if ("/".equals(symbol)) { - return left / right; - } - - return 0; - } - - - private class Node { - float number; - String symbol; - boolean isNumber; - int calLevel;//加减1,乘除2 - - public Node(float number, String symbol, boolean isNumber, int calLevel) { - this.number = number; - this.symbol = symbol; - this.isNumber = isNumber; - this.calLevel = calLevel; - } - - private boolean isLevel2() { - return calLevel == 2; - } - } - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/CalUtil.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/CalUtil.java new file mode 100644 index 0000000000..5b52ab0863 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/CalUtil.java @@ -0,0 +1,108 @@ +package me.lzb.basic.expr; + +import me.lzb.common.utils.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * Created by LZB on 2017/4/20. + */ +public class CalUtil { + + + public static void calculate(Stack symbolStack, Stack numberStack, boolean isRe) { + if (symbolStack.isEmpty()) { + return; + } + + + String symbole = symbolStack.pop(); + + float right; + float left; + + if (isRe) { + left = numberStack.pop(); + right = numberStack.pop(); + } else { + right = numberStack.pop(); + left = numberStack.pop(); + } + + float r = calculate(symbole, left, right); + + numberStack.push(r); + } + + + public static float calculate(String symbol, float left, float right) { + if ("+".equals(symbol)) { + return left + right; + } + + if ("-".equals(symbol)) { + return left - right; + } + + if ("*".equals(symbol)) { + return left * right; + } + + if ("/".equals(symbol)) { + return left / right; + } + + return 0; + } + + + public static List processInfixExpr(String expr) { + List list = new ArrayList<>(); + char[] array = expr.toCharArray(); + String number = ""; + for (int i = 0; i < array.length; i++) { + if (Character.isDigit(array[i])) { + number = number + String.valueOf(array[i]); + } else { + if (StringUtils.isNotBlank(number)) { + Node num = new Node(Float.valueOf(number), null, -1); + number = ""; + list.add(num); + } + + int calLevel = 1; + + if ("*/".indexOf(array[i]) >= 0) { + calLevel = 2; + } + + if ("()".indexOf(array[i]) >= 0) { + calLevel = 3; + } + + Node sym = new Node(0, String.valueOf(array[i]), calLevel); + + list.add(sym); + } + } + if (StringUtils.isNotBlank(number)) { + Node num = new Node(Float.valueOf(number), null, -1); + list.add(num); + } + + return list; + } + + + public static boolean isLowLevel(Node stackTop, Node next) { + return stackTop.calLevel < next.calLevel; + } + + public static void main(String[] args) { + Node n = new Node(0, "*", 2); + Node m = new Node(0, "-", 1); + System.out.println(isLowLevel(n, m)); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixExpr.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixExpr.java new file mode 100644 index 0000000000..833ee8cfda --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixExpr.java @@ -0,0 +1,71 @@ +package me.lzb.basic.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 中序表达式 + * Created by LZB on 2017/4/15. + */ +public class InfixExpr { + + + private String expr; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + List list = CalUtil.processInfixExpr(expr); + + Stack symbolStack = new Stack<>(); + Stack numberStack = new Stack<>(); + + boolean calLevel2 = false; + for (Node n : list) { + if (n.isNumber()) { + numberStack.push(n.number); + if (calLevel2) { + CalUtil.calculate(symbolStack, numberStack, false); + calLevel2 = false; + } + } else { + symbolStack.push(n.symbol); + + if (n.isLevel2()) { + calLevel2 = true; + } + } + } + + + Stack tn = new Stack<>(); + int nsize = numberStack.size(); + for (int i = 0; i < nsize; i++) { + tn.push(numberStack.pop()); + } + + numberStack = tn; + + + Stack ts = new Stack<>(); + int ssize = symbolStack.size(); + for (int i = 0; i < ssize; i++) { + ts.push(symbolStack.pop()); + } + + symbolStack = ts; + + + while (!symbolStack.isEmpty()) { + CalUtil.calculate(symbolStack, numberStack, true); + } + + + return numberStack.pop(); + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixToPostfix.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixToPostfix.java new file mode 100644 index 0000000000..d9b1d3e5a6 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/InfixToPostfix.java @@ -0,0 +1,79 @@ +package me.lzb.basic.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 中序转后序 + * Created by LZB on 2017/4/20. + */ +public class InfixToPostfix { + + private String infix; + + public InfixToPostfix(String infix) { + this.infix = infix; + } + + + public String change() { + StringBuffer sb = new StringBuffer(); + List list = CalUtil.processInfixExpr(infix); + Stack symbolStack = new Stack<>(); + + for (int i = 0; i < list.size(); i++) { + Node n = list.get(i); + //如果是数字,直接输出 + if (n.isNumber()) { + append(sb, n); + continue; + } + + //操作符部分 + + //操作符栈为空,操作符入栈 + if (symbolStack.isEmpty()) { + symbolStack.push(n); + continue; + } + + if (")".equals(n.symbol)) { + //当前操作符为),输出操作数栈内的操作符,直到遇到第一个( + while (!"(".equals(symbolStack.peek().symbol)) { + append(sb, symbolStack.pop()); + } + //遇到的第一个(, 出栈,完成一个括号 + symbolStack.pop(); + } else { + + //计算用,操作符 + //栈顶元素优先级更低,操作符入栈 + if (CalUtil.isLowLevel(symbolStack.peek(), n) || symbolStack.peek().isLevel3()) { + symbolStack.push(n); + } else { + //栈顶元素优先级高于等于当前操作符,输出操作符,直到遇到(,或者遇到优先级更低的操作符 + while (!symbolStack.isEmpty() && !symbolStack.peek().isLevel3() && !CalUtil.isLowLevel(symbolStack.peek(), n)) { + append(sb, symbolStack.pop()); + } + //当前操作符入栈 + symbolStack.push(n); + } + } + } + + + while (!symbolStack.isEmpty()) { + append(sb, symbolStack.pop()); + } + + return sb.toString().trim(); + } + + + private void append(StringBuffer sb, Node node) { + sb.append(" "); + sb.append(node.isNumber() ? (int) node.number : node.symbol); + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/Node.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/Node.java new file mode 100644 index 0000000000..1c698f1101 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/Node.java @@ -0,0 +1,28 @@ +package me.lzb.basic.expr; + +/** + * Created by LZB on 2017/4/20. + */ +public class Node { + float number; + String symbol; + int calLevel;//加减1,乘除2, ()3, 数字-1 + + public Node(float number, String symbol, int calLevel) { + this.number = number; + this.symbol = symbol; + this.calLevel = calLevel; + } + + public boolean isLevel2() { + return calLevel == 2; + } + + public boolean isLevel3() { + return calLevel == 3; + } + + public boolean isNumber(){ + return calLevel == -1; + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PostfixExpr.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PostfixExpr.java new file mode 100644 index 0000000000..22a0db2ee0 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PostfixExpr.java @@ -0,0 +1,46 @@ +package me.lzb.basic.expr; + +import me.lzb.common.utils.StringUtils; + +import java.util.Stack; + +/** + * 后缀表达式 + * Created by LZB on 2017/4/20. + */ +public class PostfixExpr { + + private String expr; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + Stack symbolStack = new Stack<>(); + Stack numberStack = new Stack<>(); + + char[] array = this.expr.toCharArray(); + String number = ""; + for (int i = 0; i < array.length; i++) { + if (Character.isDigit(array[i])) { + number = number + String.valueOf(array[i]); + } else { + if (StringUtils.isNotBlank(number)) { + numberStack.push(Float.valueOf(number)); + number = ""; + } + if (Character.isSpaceChar(array[i])) { + + + } else { + symbolStack.push(String.valueOf(array[i])); + CalUtil.calculate(symbolStack, numberStack, false); + } + } + } + return numberStack.pop(); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PrefixExpr.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PrefixExpr.java new file mode 100644 index 0000000000..27b7b2f52d --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/expr/PrefixExpr.java @@ -0,0 +1,46 @@ +package me.lzb.basic.expr; + +import me.lzb.common.utils.StringUtils; + +import java.util.Stack; + +/** + * 前缀表达式 + * Created by LZB on 2017/4/20. + */ +public class PrefixExpr { + + private String expr; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + Stack symbolStack = new Stack<>(); + Stack numberStack = new Stack<>(); + + char[] array = this.expr.toCharArray(); + String number = ""; + for (int i = array.length - 1; i >= 0; i--) { + if (Character.isDigit(array[i])) { + number = number + String.valueOf(array[i]); + } else { + if (StringUtils.isNotBlank(number)) { + numberStack.push(Float.valueOf(number)); + number = ""; + } + if (Character.isSpaceChar(array[i])) { + + + } else { + symbolStack.push(String.valueOf(array[i])); + CalUtil.calculate(symbolStack, numberStack, true); + } + } + } + return numberStack.pop(); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/InfixExprTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixExprTest.java similarity index 97% rename from group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/InfixExprTest.java rename to group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixExprTest.java index 5ca7621354..913f6ad2ee 100644 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/InfixExprTest.java +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixExprTest.java @@ -1,4 +1,4 @@ -package me.lzb.basic; +package me.lzb.basic.expr; import org.junit.After; import org.junit.Assert; diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixToPostfixTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..de92921b42 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/InfixToPostfixTest.java @@ -0,0 +1,42 @@ +package me.lzb.basic.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by LZB on 2017/4/20. + */ +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testChange() { + { + InfixToPostfix toPostfix = new InfixToPostfix("((2+3)*8+5+3)*6"); + Assert.assertEquals("2 3 + 8 * 5 + 3 + 6 *", toPostfix.change()); + } + + { + InfixToPostfix toPostfix = new InfixToPostfix("6*(5+(2+3)*8+3)"); + Assert.assertEquals("6 5 2 3 + 8 * + 3 + *", toPostfix.change()); + } + { + InfixToPostfix toPostfix = new InfixToPostfix("9+(3-1)*3+10/2"); + Assert.assertEquals("9 3 1 - 3 * + 10 2 / +", toPostfix.change()); + } + + { + InfixToPostfix toPostfix = new InfixToPostfix("10-2*3+50"); + Assert.assertEquals("10 2 3 * - 50 +", toPostfix.change()); + } + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PostfixExprTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PostfixExprTest.java new file mode 100644 index 0000000000..4a1239bcf6 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PostfixExprTest.java @@ -0,0 +1,43 @@ +package me.lzb.basic.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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PrefixExprTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PrefixExprTest.java new file mode 100644 index 0000000000..11691cda54 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/expr/PrefixExprTest.java @@ -0,0 +1,47 @@ +package me.lzb.basic.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java index 2addebeb39..f2f30f004f 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java @@ -1,5 +1,7 @@ package me.lzb.jvm.attr; +import me.lzb.jvm.cmd.ByteCodeCommand; + /** * Created by LZB on 2017/4/15. */ @@ -12,13 +14,20 @@ public class CodeAttr extends AttributeInfo { private LocalVariableTable localVarTable; private StackMapTable stackMapTable; - public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen, String code /*ByteCodeCommand[] cmds*/) { + + private ByteCodeCommand[] cmds; + + public ByteCodeCommand[] getCmds() { + return 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; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java index 224714a010..cfb4f067e8 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java @@ -18,12 +18,20 @@ public void setFlagValue(int flag) { this.flagValue = flag; } - public boolean isPublicClass(){ + public boolean isPublicClass() { return (this.flagValue & 0x0001) != 0; } - public boolean isFinalClass(){ + + public boolean isFinalClass() { return (this.flagValue & 0x0010) != 0; } + public String getFlagString(){ + if (isPublicClass()){ + return "public"; + }else { + return "not public"; + } + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java index c5de9be5ce..5fd864b8a8 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java @@ -1,8 +1,11 @@ package me.lzb.jvm.clz; +import me.lzb.jvm.constant.ClassInfo; import me.lzb.jvm.constant.ConstantPool; import me.lzb.jvm.field.Field; import me.lzb.jvm.method.Method; +import me.lzb.jvm.print.Print; +import me.lzb.jvm.print.PrintVisitor; import java.util.ArrayList; import java.util.List; @@ -10,7 +13,7 @@ /** * Created by LZB on 2017/4/14. */ -public class ClassFile { +public class ClassFile implements Print{ private String magicNumber; @@ -72,7 +75,6 @@ public void setConstantPool(ConstantPool constantPool) { } - public List getFields() { return fields; } @@ -90,9 +92,6 @@ public void setMethods(List methods) { } - - - public ClassIndex getClzIndex() { return clzIndex; } @@ -102,30 +101,62 @@ public void setClzIndex(ClassIndex clzIndex) { } - public void print(){ + public void print() { - if(this.accessFlag.isPublicClass()){ - System.out.println("Access flag : public "); - } -// System.out.println("Class Name:"+ getClassName()); +// if (this.accessFlag.isPublicClass()) { +// System.out.println("Access flag : public "); +// } +// System.out.println("Class Name:" + getClassName()); // -// System.out.println("Super Class Name:"+ getSuperClassName()); +// System.out.println("Super Class Name:" + getSuperClassName()); } + public String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } - + public String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } public int getConstantPoolCount() { return constantPool.getSize(); } - public void addField(Field f){ + public void addField(Field f) { this.fields.add(f); } - public void addMethod(Method m){ + public void addMethod(Method m) { this.methods.add(m); } + public Method getMethod(String methodName, String paramAndReturnType) { + 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(methodName) && desc.equals(paramAndReturnType)) { + return m; + } + } + + return null; + } + + public Method getMainMethod() { + return getMethod("main", "([Ljava/lang/String;)V"); + } + + @Override + public void print(PrintVisitor visitor) { + visitor.visitBasicMsg(this); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..83eec1cbc7 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java @@ -0,0 +1,21 @@ +package me.lzb.jvm.cmd; + + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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(); + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..07e35cb0ce --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,124 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.ConstantInfo; +import me.lzb.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + + +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); +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..a5fe80425b --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,20 @@ +package me.lzb.jvm.cmd; + + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..2d4d8d53a6 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,19 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..6af68455a0 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,21 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..5d87c07505 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,19 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..a34a64b5b0 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.ConstantInfo; +import me.lzb.jvm.constant.ConstantPool; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..ba7d9df3a7 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..242f02716a --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,22 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..00805c5dc7 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,29 @@ +package me.lzb.jvm.cmd; + +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..df00e5bb8e --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..b87faca257 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,64 @@ +package me.lzb.jvm.cmd; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java index 200e59834a..16ea736db1 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/14. */ @@ -16,6 +18,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visitClassInfo(this); + } + public int getUtf8Index() { return utf8Index; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java index 3bbabf2180..e1952a7a3e 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java @@ -1,9 +1,12 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.Print; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/14. */ -public abstract class ConstantInfo { +public abstract class ConstantInfo implements Print { public static final String MAGIC_NUMBER = "cafebabe"; @@ -20,11 +23,10 @@ public abstract class ConstantInfo { public static final int Utf8_info = 1; - protected ConstantPool constantPool; - public ConstantInfo(){ + public ConstantInfo() { } @@ -35,10 +37,16 @@ public ConstantInfo(ConstantPool pool) { public ConstantPool getConstantPool() { return constantPool; } - public ConstantInfo getConstantInfo(int index){ + + public ConstantInfo getConstantInfo(int index) { return this.constantPool.getConstantInfo(index); } public abstract int getType(); + + + @Override + public abstract void print(PrintVisitor visitor); + } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java index 0ebab33b39..36e77e84d9 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/15. */ @@ -17,6 +19,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visitFieldRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java index 263c185af5..bd921ccf67 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/15. */ @@ -18,6 +20,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visitMethodRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java index bdf158ec37..4cef60cc3f 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/15. */ @@ -18,6 +20,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visitNameAndType(this); + } + public int getIndex1() { return index1; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java index 7f9debba3b..88b90ca6c1 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/14. */ @@ -9,4 +11,9 @@ public class NullConstantInfo extends ConstantInfo{ public int getType() { return -1; } + + @Override + public void print(PrintVisitor visitor) { + + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java index 8ba36d8cfc..5d5fc284af 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/15. */ @@ -16,6 +18,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visitString(this); + } + public int getIndex() { return index; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java index d3f35c2fd7..9a27b3c716 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java @@ -1,5 +1,7 @@ package me.lzb.jvm.constant; +import me.lzb.jvm.print.PrintVisitor; + /** * Created by LZB on 2017/4/15. */ @@ -20,6 +22,11 @@ public int getType() { return type; } + @Override + public void print(PrintVisitor visitor) { + visitor.visistUTF8(this); + } + public String getValue() { return value; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java index bfd3cbc2c0..e265907158 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java @@ -208,7 +208,7 @@ private void parserMethod(ClassFile classFile) { int attributesCount = nextBytesToInt(2); - Method method = new Method(accessFlags, nameIndex, descriptorIndex); + Method method = new Method(classFile, accessFlags, nameIndex, descriptorIndex); for (int j = 1; j <= attributesCount; j++) { @@ -239,7 +239,11 @@ private void parserCodeAttr(int attributeNameIndex, Method method, ClassFile cla int codeLength = nextBytesToInt(4); String code = nextBytesToString(codeLength); - CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + + //处理cmd + CommandParser commandParser = new CommandParser(code); + + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, commandParser.parse(classFile)); int exceptionTableLength = nextBytesToInt(2); if (exceptionTableLength > 0) { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java new file mode 100644 index 0000000000..829b1670c7 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java @@ -0,0 +1,188 @@ +package me.lzb.jvm.loader; + +import me.lzb.common.utils.StringUtils; +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.cmd.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LZB on 2017/4/22. + */ +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"; + + + private int index; + + private final char[] data; + + public CommandParser(String codes) { + if (StringUtils.isBlank(codes)) { + throw new RuntimeException("the orignal code is not correct!"); + } + codes = codes.toUpperCase(); + data = codes.toCharArray(); + } + + private char[] nextChars(int nextLength) { + char[] target = new char[nextLength]; + System.arraycopy(data, index, target, 0, nextLength); + index = index + nextLength; + return target; + } + + private int nextCharsToInt(int nextLength) { + return Integer.valueOf(String.valueOf(nextChars(nextLength)), 16).intValue(); + } + + private String nextCharsToString(int nextLength) { + return String.valueOf(nextChars(nextLength)); + } + + private boolean hasNext() { + return index < data.length; + } + + + public ByteCodeCommand[] parse(ClassFile clzFile) { + + List cmds = new ArrayList<>(); + + while (hasNext()) { + String opCode = nextCharsToString(2); + + if (new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(nextCharsToInt(2)); + cmd.setOprand2(nextCharsToInt(2)); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(nextCharsToInt(2)); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(nextCharsToInt(2)); + 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 implement."); + } + } + + calcuateOffset(cmds); + + 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; + } + + 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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java index 9c3e9ad984..8c35d5aec5 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java @@ -1,6 +1,8 @@ package me.lzb.jvm.method; import me.lzb.jvm.attr.CodeAttr; +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.cmd.ByteCodeCommand; /** * Created by LZB on 2017/4/15. @@ -12,11 +14,11 @@ public class Method { private CodeAttr codeAttr; -// private ClassFile clzFile; + private ClassFile clzFile; - public Method(/*ClassFile clzFile,*/ int accessFlag, int nameIndex, int descriptorIndex) { -// this.clzFile = clzFile; + public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; this.accessFlag = accessFlag; this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; @@ -55,11 +57,15 @@ public void setCodeAttr(CodeAttr codeAttr) { this.codeAttr = codeAttr; } -// public ClassFile getClzFile() { -// return clzFile; -// } -// -// public void setClzFile(ClassFile clzFile) { -// this.clzFile = clzFile; -// } + public ClassFile getClzFile() { + return clzFile; + } + + public void setClzFile(ClassFile clzFile) { + this.clzFile = clzFile; + } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java new file mode 100644 index 0000000000..0b1566669a --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java @@ -0,0 +1,36 @@ +package me.lzb.jvm.print; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.ConstantInfo; +import me.lzb.jvm.constant.ConstantPool; + +/** + * Created by LZB on 2017/4/23. + */ +public class ClassPrinter { + + private ClassFile classFile; + + private ConstantPool pool; + + public ClassPrinter(ClassFile classFile) { + this.classFile = classFile; + this.pool = classFile.getConstantPool(); + } + + + public void print() { + PrintVisitor visitor = new PrintFormat(); + + classFile.print(visitor); + + System.out.println("Constant Pool:"); + + for (int i = 1; i <= pool.getSize(); i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#" + i + " = "); + constantInfo.print(visitor); + } + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/Print.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/Print.java new file mode 100644 index 0000000000..1435d46814 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/Print.java @@ -0,0 +1,10 @@ +package me.lzb.jvm.print; + +/** + * Created by LZB on 2017/4/23. + */ +public interface Print { + + public void print(PrintVisitor visitor); + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java new file mode 100644 index 0000000000..663496de8e --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java @@ -0,0 +1,57 @@ +package me.lzb.jvm.print; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.*; + +/** + * Created by LZB on 2017/4/23. + */ +public class PrintFormat implements PrintVisitor { + + + @Override + public void visitBasicMsg(ClassFile info) { + System.out.println("Access flag : " + info.getAccessFlag().getFlagString()); + + System.out.println("Class Name:" + info.getClassName()); + + System.out.println("Super Class Name:" + info.getSuperClassName()); + + System.out.println("minor version:" + info.getMinorVersion()); + + System.out.println("major version:" + info.getMajorVersion()); + + System.out.println(); + } + + + @Override + public void visistUTF8(UTF8Info info) { + System.out.println("UTF8 " + info.getValue()); + } + + @Override + public void visitClassInfo(ClassInfo info) { + System.out.println("Class #" + info.getUtf8Index() + " " + info.getClassName()); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + System.out.println("FieldRef #" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + System.out.println("MethodRef #" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + System.out.println("NameAndType #" + info.getIndex1() + ":#" + info.getIndex2()); + } + + @Override + public void visitString(StringInfo info) { + System.out.println("String #" + info.getIndex()); + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java new file mode 100644 index 0000000000..6d846786bc --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java @@ -0,0 +1,23 @@ +package me.lzb.jvm.print; + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.*; + +/** + * Created by LZB on 2017/4/23. + */ +public interface PrintVisitor { + public void visitBasicMsg(ClassFile info); + + 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); +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java index f41b313c97..b4adbcf888 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java +++ b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java @@ -3,10 +3,15 @@ import me.lzb.common.utils.ByteUtils; import me.lzb.jvm.clz.ClassFile; import me.lzb.jvm.clz.ClassIndex; +import me.lzb.jvm.cmd.BiPushCmd; +import me.lzb.jvm.cmd.ByteCodeCommand; +import me.lzb.jvm.cmd.OneOperandCmd; +import me.lzb.jvm.cmd.TwoOperandCmd; import me.lzb.jvm.constant.*; import me.lzb.jvm.field.Field; import me.lzb.jvm.loader.ClassFileLoader; import me.lzb.jvm.method.Method; +import me.lzb.jvm.print.ClassPrinter; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -20,13 +25,11 @@ public class ClassFileloaderTest { static String path1 = EmployeeV1.class.getResource("/").getPath(); -// static String path1 = "D:\\code\\learning\\coding2017\\group24\\1148285693\\learning2017\\mini-jvm\\target\\test-classes\\"; static String path2 = "C:\\temp"; static String className = "me.lzb.jvm.EmployeeV1"; private static final String FULL_QUALIFIED_CLASS_NAME = "me/lzb/jvm/EmployeeV1"; -// private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; @Before @@ -43,8 +46,8 @@ public void testPath() { String s = EmployeeV1.class.getResource("/").getPath(); String s2 = EmployeeV1.class.getResource("").getPath(); - System.out.println(s); - System.out.println(s2); +// System.out.println(s); +// System.out.println(s2); } @@ -266,4 +269,88 @@ private void assertMethodEquals(ConstantPool pool, Method m, String expectedName Assert.assertEquals(expectedCode, code); } + /** + * 第四次JVM + */ + + + @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 #1", cmds[1]); + assertOpCodeEquals("4: aload_0", cmds[2]); + assertOpCodeEquals("5: aload_1", cmds[3]); + assertOpCodeEquals("6: putfield #2", cmds[4]); + assertOpCodeEquals("9: aload_0", cmds[5]); + assertOpCodeEquals("10: iload_2", cmds[6]); + assertOpCodeEquals("11: putfield #3", 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 #2", cmds[2]); + assertOpCodeEquals("5: return", cmds[3]); + + } + + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + ByteCodeCommand[] cmds = sayHelloMethod.getCmds(); + + assertOpCodeEquals("0: getstatic #4", cmds[0]); + assertOpCodeEquals("3: ldc #5", cmds[1]); + assertOpCodeEquals("5: invokevirtual #6", cmds[2]); + assertOpCodeEquals("8: return", cmds[3]); + + } + + { + Method mainMethod = this.clzFile.getMainMethod(); + + ByteCodeCommand[] cmds = mainMethod.getCmds(); + + assertOpCodeEquals("0: new #7", cmds[0]); + assertOpCodeEquals("3: dup", cmds[1]); + assertOpCodeEquals("4: ldc #8", cmds[2]); + assertOpCodeEquals("6: bipush 29", cmds[3]); + assertOpCodeEquals("8: invokespecial #9", cmds[4]); + assertOpCodeEquals("11: astore_1", cmds[5]); + assertOpCodeEquals("12: aload_1", cmds[6]); + assertOpCodeEquals("13: invokevirtual #10", 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); + } + + @Test + public void testPrint() { + ClassPrinter classPrinter = new ClassPrinter(clzFile); + classPrinter.print(); + } } From 80c5c9b174c99569c7e83360f6758dddf90180a9 Mon Sep 17 00:00:00 2001 From: HuiZhou-Xmu <1814014897@qq.com> Date: Sun, 23 Apr 2017 19:34:20 +0800 Subject: [PATCH 109/151] =?UTF-8?q?=E7=AC=AC=E5=85=AD=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zhouhui/src/week06/expr/InfixExpr.java | 150 ++++++++++ .../src/week06/expr/InfixExprTest.java | 48 +++ .../src/week06/jvm/attr/AttributeInfo.java | 19 ++ .../zhouhui/src/week06/jvm/attr/CodeAttr.java | 93 ++++++ .../src/week06/jvm/attr/LineNumberTable.java | 54 ++++ .../week06/jvm/attr/LocalVariableItem.java | 39 +++ .../week06/jvm/attr/LocalVariableTable.java | 44 +++ .../src/week06/jvm/attr/StackMapTable.java | 30 ++ .../src/week06/jvm/clz/AccessFlag.java | 25 ++ .../zhouhui/src/week06/jvm/clz/ClassFile.java | 92 ++++++ .../src/week06/jvm/clz/ClassIndex.java | 19 ++ .../src/week06/jvm/constant/ClassInfo.java | 24 ++ .../src/week06/jvm/constant/ConstantInfo.java | 29 ++ .../src/week06/jvm/constant/ConstantPool.java | 29 ++ .../src/week06/jvm/constant/FieldRefInfo.java | 54 ++++ .../week06/jvm/constant/MethodRefInfo.java | 55 ++++ .../week06/jvm/constant/NameAndTypeInfo.java | 45 +++ .../week06/jvm/constant/NullConstantInfo.java | 13 + .../src/week06/jvm/constant/StringInfo.java | 26 ++ .../src/week06/jvm/constant/UTF8Info.java | 32 ++ .../zhouhui/src/week06/jvm/field/Field.java | 45 +++ .../week06/jvm/loader/ByteCodeIterator.java | 55 ++++ .../week06/jvm/loader/ClassFileLoader.java | 140 +++++++++ .../week06/jvm/loader/ClassFileParser.java | 174 +++++++++++ .../zhouhui/src/week06/jvm/method/Method.java | 76 +++++ .../week06/jvm/test/ClassFileloaderTest.java | 273 ++++++++++++++++++ .../src/week06/jvm/test/EmployeeV1.java | 28 ++ .../zhouhui/src/week06/jvm/util/Util.java | 24 ++ 28 files changed, 1735 insertions(+) create mode 100644 group01/1814014897/zhouhui/src/week06/expr/InfixExpr.java create mode 100644 group01/1814014897/zhouhui/src/week06/expr/InfixExprTest.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/AttributeInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/CodeAttr.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/LineNumberTable.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableItem.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableTable.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/attr/StackMapTable.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/clz/AccessFlag.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/clz/ClassFile.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/clz/ClassIndex.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/ClassInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantPool.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/FieldRefInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/MethodRefInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/NameAndTypeInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/NullConstantInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/StringInfo.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/constant/UTF8Info.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/field/Field.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/loader/ByteCodeIterator.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/loader/ClassFileLoader.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/loader/ClassFileParser.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/method/Method.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/test/ClassFileloaderTest.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/test/EmployeeV1.java create mode 100644 group01/1814014897/zhouhui/src/week06/jvm/util/Util.java diff --git a/group01/1814014897/zhouhui/src/week06/expr/InfixExpr.java b/group01/1814014897/zhouhui/src/week06/expr/InfixExpr.java new file mode 100644 index 0000000000..eebc672005 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/expr/InfixExpr.java @@ -0,0 +1,150 @@ +package week06.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + float result = 0; + + Stack operandStack = new Stack(); // 运算数栈 + Stack operaterStack = new Stack(); // 运算符栈 + + char[] exprCharArr = expr.toCharArray(); + List exprStringList = new ArrayList(); + addOperandAndOperater(exprCharArr, exprStringList); + + for (int i = 0; i < exprStringList.size(); i++) { + if (isOperand(exprStringList.get(i))) { + operandStack.push(exprStringList.get(i)); + } else if (isOperater(exprStringList.get(i))) { + operaterStack.push(exprStringList.get(i)); + } else { + throw new RuntimeException("this operater has not yet implemented."); + } + + if (operaterStack.size() == 2) { + + String operater_1 = (String) operaterStack.pop(); + String operater_2 = (String) operaterStack.pop(); + if (hasTheSameOrHighPriority(operater_2, operater_1)) { + + String operand_1 = (String) operandStack.pop(); + String operand_2 = (String) operandStack.pop(); + operation(operandStack, operater_2, operand_1, operand_2); + + operaterStack.push(operater_1); + } else if (hasTheLowPriority(operater_2, operater_1)) { + + operandStack.push(exprStringList.get(++i)); + String operand_1 = (String) operandStack.pop(); + String operand_2 = (String) operandStack.pop(); + operation(operandStack, operater_1, operand_1, operand_2); + + operaterStack.push(operater_2); + } + } + + if (i == exprStringList.size() - 1) { + + String operater = (String) operaterStack.pop(); + String operand_1 = (String) operandStack.pop(); + String operand_2 = (String) operandStack.pop(); + operation(operandStack, operater, operand_1, operand_2); + + result = (float) Integer.parseInt((String) operandStack.pop()); + } + } + + return result; + } + + private void addOperandAndOperater(char[] exprCharArr, List exprStringList) { + for (int i = 0; i < exprCharArr.length; i++) { + if (isOperand(exprCharArr[i])) { + StringBuilder sb = new StringBuilder(); + sb.append(exprCharArr[i]); + if (i < exprCharArr.length - 1) { + while (i < exprCharArr.length - 1 && isOperand(exprCharArr[i + 1])) { + sb.append(exprCharArr[i + 1]); + i++; + } + } + exprStringList.add(sb.toString()); + } else if (isOperater(exprCharArr[i])) { + exprStringList.add(exprCharArr[i] + ""); + } + } + } + + private boolean isOperand(char c) { + return !isOperater(c); + } + + private boolean isOperater(char c) { + if (c == '+' || c == '-' || c == '*' || c == '/') { + return true; + } + return false; + } + + private boolean isOperand(String c) { + return !isOperater(c); + } + + // 字符串相等用equals()比较. + private boolean isOperater(String c) { + if (c.equals("+") || c.equals("-") || c.equals("*") || c.equals("/")) { + return true; + } + return false; + } + + // operater_1 has the same or high priority compare with the operater_2. + private boolean hasTheSameOrHighPriority(Object operater_1, Object operater_2) { + if ((operater_1.equals("+") && operater_2.equals("+")) || (operater_1.equals("+") && operater_2.equals("-")) + || (operater_1.equals("-") && operater_2.equals("+")) + || (operater_1.equals("-") && operater_2.equals("-")) + || (operater_1.equals("*") && operater_2.equals("*")) + || (operater_1.equals("*") && operater_2.equals("/")) + || (operater_1.equals("/") && operater_2.equals("*")) + || (operater_1.equals("/") && operater_2.equals("/")) + || (operater_1.equals("*") && operater_2.equals("+")) + || (operater_1.equals("*") && operater_2.equals("-")) + || (operater_1.equals("/") && operater_2.equals("+")) + || (operater_1.equals("/") && operater_2.equals("-"))) { + return true; + } + return false; + } + + //// operater_1 has the low priority compare with the operater_2. + private boolean hasTheLowPriority(Object operater_1, Object operater_2) { + if ((operater_1.equals("+") && operater_2.equals("*")) || (operater_1.equals("+") && operater_2.equals("/")) + || (operater_1.equals("-") && operater_2.equals("*")) + || (operater_1.equals("-") && operater_2.equals("/"))) { + return true; + } + return false; + } + + private void operation(Stack operandStack, String operater, String operand_1, String operand_2) { + if (operater.equals("+")) { + operandStack.push((Integer.parseInt(operand_2) + Integer.parseInt(operand_1)) + ""); + } else if (operater.equals("-")) { + operandStack.push((Integer.parseInt(operand_2) - Integer.parseInt(operand_1)) + ""); + } else if (operater.equals("*")) { + operandStack.push((Integer.parseInt(operand_2) * Integer.parseInt(operand_1)) + ""); + } else if (operater.equals("/")) { + operandStack.push((Integer.parseInt(operand_2) / Integer.parseInt(operand_1)) + ""); + } + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/expr/InfixExprTest.java b/group01/1814014897/zhouhui/src/week06/expr/InfixExprTest.java new file mode 100644 index 0000000000..8ce2c7d1de --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package week06.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/attr/AttributeInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..80a7b0aa5e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package week06.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/group01/1814014897/zhouhui/src/week06/jvm/attr/CodeAttr.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..de2ed92a6e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/CodeAttr.java @@ -0,0 +1,93 @@ +package week06.jvm.attr; + +import week06.jvm.clz.ClassFile; +import week06.jvm.constant.ConstantPool; +import week06.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); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.nextU2ToInt(); + + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table,just ignore it"); + } + + int subAttrCount = iter.nextU2ToInt(); + + for (int i = 1; i <= subAttrCount; i++) { + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + iter.back(2); + + 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; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/attr/LineNumberTable.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..4a31d1ebbe --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/LineNumberTable.java @@ -0,0 +1,54 @@ +package week06.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import week06.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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; + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableItem.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..2c1c056d86 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package week06.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/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableTable.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..73140faa4e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/LocalVariableTable.java @@ -0,0 +1,44 @@ +package week06.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import week06.jvm.constant.ConstantPool; + +import week06.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + 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; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/attr/StackMapTable.java b/group01/1814014897/zhouhui/src/week06/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..2580f1b7aa --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package week06.jvm.attr; + + +import week06.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/group01/1814014897/zhouhui/src/week06/jvm/clz/AccessFlag.java b/group01/1814014897/zhouhui/src/week06/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..8e313e8fb1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package week06.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassFile.java b/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..029f680c9b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package week06.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import week06.jvm.constant.ClassInfo; +import week06.jvm.constant.ConstantPool; +import week06.jvm.field.Field; +import week06.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + private String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassIndex.java b/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..854ad0aca7 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package week06.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/ClassInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..bfd827374f --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package week06.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a3efac308d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package week06.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantPool.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..347ddbbde9 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package week06.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/FieldRefInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..4c1840b3d7 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package week06.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/MethodRefInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..da4f98b9b6 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package week06.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/NameAndTypeInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..28d6de6325 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package week06.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/NullConstantInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..faf8d31e45 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package week06.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/StringInfo.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..caaca2847b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package week06.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/constant/UTF8Info.java b/group01/1814014897/zhouhui/src/week06/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..000c47bd1a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package week06.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/field/Field.java b/group01/1814014897/zhouhui/src/week06/jvm/field/Field.java new file mode 100644 index 0000000000..09cc693300 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/field/Field.java @@ -0,0 +1,45 @@ +package week06.jvm.field; + +import week06.jvm.constant.ConstantPool; +import week06.jvm.constant.UTF8Info; +import week06.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 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("attribCount:"+attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex, pool); + + if (attribCount > 0) { + throw new RuntimeException("Field Attribute has not been implemented"); + } + return f; + } + + public String toString(){ + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + return name + ":" + desc; + } + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/loader/ByteCodeIterator.java b/group01/1814014897/zhouhui/src/week06/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..5f3dceb30c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,55 @@ +package week06.jvm.loader; + +import java.util.Arrays; + +import week06.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/loader/ClassFileLoader.java b/group01/1814014897/zhouhui/src/week06/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..0a3c96e78a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package week06.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import week06.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + 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); + } + + +} diff --git a/group01/1814014897/zhouhui/src/week06/jvm/test/EmployeeV1.java b/group01/1814014897/zhouhui/src/week06/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..3e5fb09863 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package week06.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group01/1814014897/zhouhui/src/week06/jvm/util/Util.java b/group01/1814014897/zhouhui/src/week06/jvm/util/Util.java new file mode 100644 index 0000000000..94670540d1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week06/jvm/util/Util.java @@ -0,0 +1,24 @@ +package week06.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i Date: Sun, 23 Apr 2017 21:24:20 +0800 Subject: [PATCH 110/151] printer --- .../minijvm/constant/ClassInfo.java | 4 ++ .../minijvm/constant/ConstantInfo.java | 11 +++ .../minijvm/constant/ConstantPool.java | 2 +- .../minijvm/constant/FieldRefInfo.java | 5 ++ .../minijvm/constant/MethodRefInfo.java | 5 ++ .../minijvm/constant/NameAndTypeInfo.java | 5 ++ .../minijvm/constant/NullConstantInfo.java | 4 ++ .../minijvm/constant/StringInfo.java | 6 ++ .../coding2017/minijvm/constant/UTF8Info.java | 4 ++ .../minijvm/print/ClassFilePrinter.java | 8 ++- .../minijvm/print/ConstantPoolPrinter.java | 72 ++++++++++++++++++- 11 files changed, 121 insertions(+), 5 deletions(-) diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java index e2e0f50f61..d8cba51f62 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java @@ -23,4 +23,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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java index 663c493b57..9275387556 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java @@ -25,5 +25,16 @@ public ConstantPool getConstantPool() { 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); + + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java index ea0e135a23..d28601f4ba 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java @@ -23,7 +23,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java index b74fb427ba..521c010f7b 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java @@ -51,4 +51,9 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java index cc5352db6e..287c907259 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java @@ -49,6 +49,11 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java index d1cd005111..990c0f6a01 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java @@ -42,4 +42,9 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java index 38eef91f32..06c20e5b4f 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java @@ -9,5 +9,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java index 8f23231e72..00b9b9b706 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java @@ -22,5 +22,11 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java index d94a267bbc..c0a7b4e0c5 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java @@ -26,6 +26,10 @@ public String getValue() { public void setValue(String value) { this.value = value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java index 6615a189f5..2d7967cb41 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ClassFilePrinter.java @@ -20,7 +20,7 @@ public void print(){ System.out.println("minor version:" + clzFile.getMinorVersion()); - System.out.println("major version:" + clzFile.getMinorVersion()); + System.out.println("major version:" + clzFile.getMajorVersion()); ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); cnstPoolPrinter.print(); @@ -31,10 +31,12 @@ public void print(){ } public static void main(String[] args){ - String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; +// String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + String path = "E:\\javaImprove\\git\\group24\\121111914\\src\\com\\github\\ipk2015\\coding2017\\minijvm\\bin"; ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); - String className = "com.coderising.jvm.test.EmployeeV1"; +// String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "EmployeeV1"; ClassFile clzFile = loader.loadClass(className); diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java index 295c509941..17b88d9932 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/print/ConstantPoolPrinter.java @@ -1,6 +1,13 @@ package com.github.ipk2015.coding2017.minijvm.print; +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; +import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; +import com.github.ipk2015.coding2017.minijvm.constant.NameAndTypeInfo; +import com.github.ipk2015.coding2017.minijvm.constant.StringInfo; +import com.github.ipk2015.coding2017.minijvm.constant.UTF8Info; public class ConstantPoolPrinter { ConstantPool pool; @@ -11,8 +18,71 @@ public void print(){ System.out.println("Constant Pool:"); + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor(){ + + @Override + public void visitClassInfo(ClassInfo info) { + int utf8Index = info.getUtf8Index(); + String className = info.getClassName(); + sop("Class\t\t"+"#"+utf8Index+"\t\t// "+className); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + int classInfoIndex = info.getClassInfoIndex(); + int nameAndTypeIndex = info.getNameAndTypeIndex(); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + sop("Fieldref\t\t"+"#"+classInfoIndex+".#"+nameAndTypeIndex+"\t\t// " + +className+"."+fieldName+":"+fieldType); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + int classInfoIndex = info.getClassInfoIndex(); + int nameAndTypeIndex = info.getNameAndTypeIndex(); + String className = info.getClassName(); + String methodName = info.getMethodName(); + String paramAndReturnType = info.getParamAndReturnType(); + sop("Methodref\t\t"+"#"+classInfoIndex+".#"+nameAndTypeIndex+"\t\t// " + +className+"."+methodName+":"+paramAndReturnType); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + int index1 = info.getIndex1(); + int index2 = info.getIndex2(); + String name = info.getName(); + String typeInfo = info.getTypeInfo(); + sop("NameAndType\t"+"#"+index1+".#"+index2+"\t\t// "+name+":"+typeInfo); + } + + @Override + public void visitString(StringInfo info) { + int index = info.getIndex(); + String utf8String = info.getConstantPool().getUTF8String(index); + sop("String\t\t"+"#"+index+"\t\t// "+utf8String); + } + + @Override + public void visistUTF8(UTF8Info info) { + sop("Utf8\t\t"+info.getValue()); + } + + }; + int size = pool.getSize(); + for(int i = 1;i < size+1;i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("\t"+"#"+i+" = "); + constantInfo.accept(visitor); + } - + } + + public static void sop(String s){ + System.out.println(s); } } From 5e88c64915c5a0458611c781c663994c91fb919e Mon Sep 17 00:00:00 2001 From: maishihang <446031103@qq.com> Date: Sun, 23 Apr 2017 21:47:30 +0800 Subject: [PATCH 111/151] compele jvm the second work --- .../com/datastructure/stack/StackUtil.java | 53 ++++++++++-- .../datastructure/stack/StackUtilTest.java | 80 +++++++++++++++++++ 2 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 group12/446031103/src/com/datastructure/stack/StackUtilTest.java diff --git a/group12/446031103/src/com/datastructure/stack/StackUtil.java b/group12/446031103/src/com/datastructure/stack/StackUtil.java index 7cab99ede3..2d4040d25d 100644 --- a/group12/446031103/src/com/datastructure/stack/StackUtil.java +++ b/group12/446031103/src/com/datastructure/stack/StackUtil.java @@ -7,13 +7,40 @@ public class StackUtil { * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ - public static void reverse(Stack s) { + //错误,面向对象错误 + /*public static void reverse(Stack s) { Stack temp = new Stack(); while(!s.isEmpty()){ temp.push(s.pop()); } s = temp; + }*/ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + + Stack tmp = new Stack(); + while(!s.isEmpty()){ + tmp.push(s.pop()); + } + while(!tmp.isEmpty()){ + Object top = tmp.pop(); + addToBottom(s,top); + } + + + } + public static void addToBottom(Stack s, Object value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Object top = s.pop(); + addToBottom(s,value); + s.push(top); + } } + /** * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 @@ -21,6 +48,9 @@ public static void reverse(Stack s) { * @param o */ public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } Stack temp = new Stack(); while(!s.isEmpty()){ Object result=s.pop(); @@ -75,7 +105,7 @@ public static boolean isValidPairs(String s){ } } }else{ - char result=c[clength/2+1]; + char result=c[clength/2]; if(contain(result)){ return false; }; @@ -83,7 +113,7 @@ public static boolean isValidPairs(String s){ if(i s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} From d5cd0b186210699a39863d940213989e83c49b2e Mon Sep 17 00:00:00 2001 From: sdnb Date: Sun, 23 Apr 2017 23:01:40 +0800 Subject: [PATCH 112/151] =?UTF-8?q?=E5=90=8E=E7=BC=80/=E5=89=8D=E7=BC=80/?= =?UTF-8?q?=E4=B8=AD=E7=BC=80=E8=BD=AC=E5=90=8E=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coderising/jvm/print/SimpleVistor.java | 56 +++++++++++++++ .../com/coding/week6/exprNew/InfixExpr.java | 11 ++- .../com/coding/week6/exprNew/Operator.java | 10 +-- .../java/com/coding/week6/exprNew/Token.java | 23 +++++-- .../com/coding/week6/exprNew/TokenParser.java | 11 ++- .../java/com/coding/week7/InfixToPostfix.java | 69 +++++++++++++++++++ .../java/com/coding/week7/PostfixExpr.java | 39 +++++++++++ .../java/com/coding/week7/PrefixExpr.java | 43 ++++++++++++ .../week6/exprNew/InfixExprTestTest.java | 3 +- .../com/coding/week7/InfixToPostfixTest.java | 34 +++++++++ .../com/coding/week7/PostfixExprTest.java | 41 +++++++++++ .../java/com/coding/week7/PrefixExprTest.java | 45 ++++++++++++ 12 files changed, 367 insertions(+), 18 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java create mode 100644 group24/494800949/src/main/java/com/coding/week7/InfixToPostfix.java create mode 100644 group24/494800949/src/main/java/com/coding/week7/PostfixExpr.java create mode 100644 group24/494800949/src/main/java/com/coding/week7/PrefixExpr.java create mode 100644 group24/494800949/src/test/java/com/coding/week7/InfixToPostfixTest.java create mode 100644 group24/494800949/src/test/java/com/coding/week7/PostfixExprTest.java create mode 100644 group24/494800949/src/test/java/com/coding/week7/PrefixExprTest.java diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java new file mode 100644 index 0000000000..e10e7885ba --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java @@ -0,0 +1,56 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.print; + +import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; + +import java.util.Formatter; + +/** + * Created by Administrator on 2017/4/23 0023. + */ +public class SimpleVistor implements ConstantInfo.Visitor { + private Formatter formatter = new Formatter(System.out); + private String format = " = %-20s %-20s %-100s\n"; + private static final String HASH_KEY = "#"; + private static final String DOUBLE_SLASH = "// "; + private static final String DOT = "."; + private static final String COLON = ":"; + + @Override + public void visitClassInfo(ClassInfo info) { + formatter.format(format, "Class", + HASH_KEY + info.getUtf8Index(), + DOUBLE_SLASH + info.getClassName()); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)info.getConstantInfo(info.getNameAndTypeIndex()); + formatter.format(format, "Fieldref", + HASH_KEY + info.getClassInfoIndex() + DOT + HASH_KEY + info.getNameAndTypeIndex(), + DOUBLE_SLASH + info.getClassName() + DOT + nameAndTypeInfo.getName() + COLON + nameAndTypeInfo.getTypeInfo()); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + formatter.format(format, "Methodref", + HASH_KEY + info.getClassInfoIndex() + DOT + HASH_KEY + info.getNameAndTypeIndex(), + DOUBLE_SLASH + info.getClassName() + DOT + info.getMethodName()); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + formatter.format(format, "NameAndType", + HASH_KEY + info.getIndex1() + COLON + HASH_KEY + info.getIndex2(), + DOUBLE_SLASH + info.getName() + COLON + info.getTypeInfo()); + } + + @Override + public void visitString(StringInfo info) { + formatter.format(format, "String", HASH_KEY + info.getIndex(), DOUBLE_SLASH + info.toString()); + } + + @Override + public void visistUTF8(UTF8Info info) { + formatter.format(format, "Utf8", info.getValue(), ""); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java index 41704db5db..3962b49fce 100644 --- a/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/InfixExpr.java @@ -31,21 +31,20 @@ public void fillStack(Stack numberStack, Stack operatorStack) { List tokens = tokenParser.parse(expr); for (Token token : tokens) { if (token.isNumber()) { - numberStack.push((float)token.getIntValue()); - continue; + numberStack.push(token.getFloatValue()); } - if (token.isOperator()) { + else if (token.isOperator()) { Operator o = token.getOperator(); if (operatorStack.isEmpty()) { operatorStack.push(o); }else { - Operator topO = (Operator)operatorStack.peek(); - if (o.hasHigherPriority(topO)) { + Operator top = (Operator)operatorStack.peek(); + if (o.hasHigherPriority(top)) { operatorStack.push(o); } else { float operTop1 = (float) numberStack.pop(); float operTop2 = (float) numberStack.pop(); - numberStack.push(topO.apply(operTop2, operTop1)); + numberStack.push(top.apply(operTop2, operTop1)); operatorStack.pop(); operatorStack.push(o); } diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java index b91c8158bf..f6b4681e46 100644 --- a/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/Operator.java @@ -10,28 +10,28 @@ */ public enum Operator { ADD("+", 1) { - float apply(float x, float y){ + public float apply(float x, float y){ return x + y; } }, SUB("-", 1) { @Override - float apply(float x, float y) { + public float apply(float x, float y) { return x - y; } }, MULT("*", 2) { @Override - float apply(float x, float y) { + public float apply(float x, float y) { return x * y; } }, DIVI("/", 2) { @Override - float apply(float x, float y) { + public float apply(float x, float y) { return x / y; } }; @@ -59,7 +59,7 @@ public static List symbols() { return symbos; } - abstract float apply(float x, float y); + public abstract float apply(float x, float y); private static final Map map = new HashMap(); diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java index d987ac47b4..c925a22705 100644 --- a/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/Token.java @@ -5,11 +5,13 @@ */ public class Token { - private int type; + private int type; private String value; - static final int NUMBER = 1; + static final int NUMBER = 1; static final int OPERATOR = 2; + static final int LEFT_BRACKET = 3; + static final int RIGHT_BRACKET = 4; public Token(int type, String value) { this.type = type; this.value = value; @@ -24,7 +26,15 @@ public boolean isOperator(){ return type == OPERATOR; } - public int getIntValue() { + public boolean isLeftBracket() { + return type == LEFT_BRACKET; + } + + public boolean isRightBracket() { + return type == RIGHT_BRACKET; + } + + public float getFloatValue() { if (isNumber()) return Integer.valueOf(value); else @@ -32,7 +42,7 @@ public int getIntValue() { } public String toString() { - return type+":"+value; + return value; } @@ -45,4 +55,9 @@ public Operator getOperator() { } + public String getValue() { + return value; + } + + } diff --git a/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java b/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java index ee90c39701..52757dc0c7 100644 --- a/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java +++ b/group24/494800949/src/main/java/com/coding/week6/exprNew/TokenParser.java @@ -25,10 +25,19 @@ public List parse(String expr) { token = new Token(Token.OPERATOR, c+""); tokens.add(token); i++; + } else if (String.valueOf(c).matches("\\s")){ + i++; + } else if (c == '(') { + token = new Token(Token.LEFT_BRACKET, String.valueOf(c)); + tokens.add(token); + i++; + } else if (c == ')') { + token = new Token(Token.RIGHT_BRACKET, String.valueOf(c)); + tokens.add(token); + i++; } else { throw new RuntimeException(c +" is not number or support operator"); } - } return tokens; } diff --git a/group24/494800949/src/main/java/com/coding/week7/InfixToPostfix.java b/group24/494800949/src/main/java/com/coding/week7/InfixToPostfix.java new file mode 100644 index 0000000000..6717f571ee --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week7/InfixToPostfix.java @@ -0,0 +1,69 @@ +package com.coding.week7; + +import com.coding.week6.exprNew.Operator; +import com.coding.week6.exprNew.Token; +import com.coding.week6.exprNew.TokenParser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + /** + 1 建立符号栈 + 2 顺序扫描中序表达式 + a) 是数字, 直接输出 + b) 是运算符 + i : “(” 直接入栈 + ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出 + iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。 + 3 扫描完后, 将栈中剩余符号依次输出 + */ + List targetTokens = new ArrayList<>(); + TokenParser tokenParser = new TokenParser(); + List sourceTokes = tokenParser.parse(expr); + Stack operStack = new Stack(); + for (Token token : sourceTokes) { + if (token.isNumber()) { + targetTokens.add(token); + } else { + //左括号 + if (token.isLeftBracket()) { + operStack.push(token); + //右括号 + } else if (token.isRightBracket()) { + while (!operStack.isEmpty()) { + Token t = operStack.peek(); + if (t.isLeftBracket()) { + operStack.pop(); + break; + } else { + targetTokens.add(operStack.pop()); + } + } + //普通运算符 + } else { + Operator oper = token.getOperator(); + if (!operStack.isEmpty()) { + Token t = operStack.peek(); + while (!t.isLeftBracket() && !oper.hasHigherPriority(t.getOperator()) && !operStack.isEmpty()) { + t = operStack.pop(); + targetTokens.add(t); + } + } + operStack.push(token); + } + } + } + //将栈中操作符全部输出 + while (!operStack.isEmpty()) { + targetTokens.add(operStack.pop()); + } + return targetTokens; + } + + + +} diff --git a/group24/494800949/src/main/java/com/coding/week7/PostfixExpr.java b/group24/494800949/src/main/java/com/coding/week7/PostfixExpr.java new file mode 100644 index 0000000000..8fb78e6a8d --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week7/PostfixExpr.java @@ -0,0 +1,39 @@ +package com.coding.week7; + +import com.coding.week6.exprNew.Operator; +import com.coding.week6.exprNew.Token; +import com.coding.week6.exprNew.TokenParser; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + final Stack numStack; + final Stack operStack; + + public PostfixExpr(String expr) { + this.expr = expr; + this.numStack = new Stack<>(); + this.operStack = new Stack<>(); + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(token.getFloatValue()); + } else if (token.isOperator()) { + if (numStack.size() >= 2) { + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = token.getOperator().apply(num2, num1); + numStack.push(result); + } + } + } + return numStack.pop(); + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week7/PrefixExpr.java b/group24/494800949/src/main/java/com/coding/week7/PrefixExpr.java new file mode 100644 index 0000000000..1bb8e4fd8a --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week7/PrefixExpr.java @@ -0,0 +1,43 @@ +package com.coding.week7; + +import com.coding.week6.exprNew.Operator; +import com.coding.week6.exprNew.Token; +import com.coding.week6.exprNew.TokenParser; + +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + final Stack numStack; + final Stack operStack; + + public PrefixExpr(String expr) { + this.expr = expr; + numStack = new Stack<>(); + operStack = new Stack<>(); + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + parser.parse(expr); + List tokens = parser.parse(expr); + Collections.reverse(tokens); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(token.getFloatValue()); + } else if (token.isOperator()) { + if (numStack.size() >= 2) { + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = token.getOperator().apply(num1, num2); + numStack.push(result); + } + } + } + return numStack.pop(); + } + + +} diff --git a/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java b/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java index d8f4a5390f..9939878611 100644 --- a/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java +++ b/group24/494800949/src/test/java/com/coding/week6/exprNew/InfixExprTestTest.java @@ -1,7 +1,6 @@ -package ew; +package com.coding.week6.exprNew; -import com.coding.week6.exprNew.InfixExpr; import org.junit.After; import org.junit.Assert; import org.junit.Before; diff --git a/group24/494800949/src/test/java/com/coding/week7/InfixToPostfixTest.java b/group24/494800949/src/test/java/com/coding/week7/InfixToPostfixTest.java new file mode 100644 index 0000000000..54a59316d6 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week7/InfixToPostfixTest.java @@ -0,0 +1,34 @@ +package com.coding.week7; + +import com.coding.week6.exprNew.Token; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +/** + * Created by Administrator on 2017/4/23 0023. + */ +public class InfixToPostfixTest { + + @Test + public void testConvert() throws Exception { + { + String expr = "9+(3-1)*3+10/2";//"9 3 1-3*+ 10 2/+" + List tokens = InfixToPostfix.convert(expr); + System.out.println(tokens); + Assert.assertEquals("9", tokens.get(0).toString()); + Assert.assertEquals("3", tokens.get(1).toString()); + Assert.assertEquals("1", tokens.get(2).toString()); + Assert.assertEquals("-", tokens.get(3).toString()); + Assert.assertEquals("3", tokens.get(4).toString()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals("+", tokens.get(6).toString()); + Assert.assertEquals("10", tokens.get(7).toString()); + Assert.assertEquals("2", tokens.get(8).toString()); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals("+", tokens.get(10).toString()); + } + + } +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week7/PostfixExprTest.java b/group24/494800949/src/test/java/com/coding/week7/PostfixExprTest.java new file mode 100644 index 0000000000..bde078a97e --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week7/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.week7; + + + +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/group24/494800949/src/test/java/com/coding/week7/PrefixExprTest.java b/group24/494800949/src/test/java/com/coding/week7/PrefixExprTest.java new file mode 100644 index 0000000000..bb2061303e --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week7/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.week7; + +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); + } + + + } + +} From 54ac61a8938c1102af44af04a76cb92d3119fad2 Mon Sep 17 00:00:00 2001 From: sdnb Date: Sun, 23 Apr 2017 23:02:29 +0800 Subject: [PATCH 113/151] javap --- group24/494800949/EmployeeV1-javap.txt | 164 ++++++++++++++++++ .../jvm/print/ClassFilePrinter.java | 45 +++++ .../jvm/print/ConstantPoolPrinter.java | 34 ++++ .../coding/week6/exprNew/TokenParserTest.java | 2 +- 4 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 group24/494800949/EmployeeV1-javap.txt create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java diff --git a/group24/494800949/EmployeeV1-javap.txt b/group24/494800949/EmployeeV1-javap.txt new file mode 100644 index 0000000000..466714a1dd --- /dev/null +++ b/group24/494800949/EmployeeV1-javap.txt @@ -0,0 +1,164 @@ +$ javap -verbose EmployeeV1 +警告: 二进制文件EmployeeV1包含com.coderising.jvm.test.EmployeeV1 +Classfile /H:/sourceCode/coding2017/group24/494800949/EmployeeV1.class + Last modified 2017-4-9; size 1056 bytes + MD5 checksum 8454b8999ccc9a2ae26a405d47558825 + Compiled from "EmployeeV1.java" +public class com.coderising.jvm.test.EmployeeV1 + minor version: 0 + major version: 52 + flags: ACC_PUBLIC, ACC_SUPER +Constant pool: + #1 = Class #2 // com/coderising/jvm/test/EmployeeV1 + #2 = Utf8 com/coderising/jvm/test/EmployeeV1 + #3 = Class #4 // java/lang/Object + #4 = Utf8 java/lang/Object + #5 = Utf8 name + #6 = Utf8 Ljava/lang/String; + #7 = Utf8 age + #8 = Utf8 I + #9 = Utf8 + #10 = Utf8 (Ljava/lang/String;I)V + #11 = Utf8 Code + #12 = Methodref #3.#13 // java/lang/Object."":()V + #13 = NameAndType #9:#14 // "":()V + #14 = Utf8 ()V + #15 = Fieldref #1.#16 // com/coderising/jvm/test/EmployeeV1.name:Ljava/lang/String; + #16 = NameAndType #5:#6 // name:Ljava/lang/String; + #17 = Fieldref #1.#18 // com/coderising/jvm/test/EmployeeV1.age:I + #18 = NameAndType #7:#8 // age:I + #19 = Utf8 LineNumberTable + #20 = Utf8 LocalVariableTable + #21 = Utf8 this + #22 = Utf8 Lcom/coderising/jvm/test/EmployeeV1; + #23 = Utf8 setName + #24 = Utf8 (Ljava/lang/String;)V + #25 = Utf8 setAge + #26 = Utf8 (I)V + #27 = Utf8 sayHello + #28 = Fieldref #29.#31 // java/lang/System.out:Ljava/io/PrintStream; + #29 = Class #30 // java/lang/System + #30 = Utf8 java/lang/System + #31 = NameAndType #32:#33 // out:Ljava/io/PrintStream; + #32 = Utf8 out + #33 = Utf8 Ljava/io/PrintStream; + #34 = String #35 // Hello , this is class Employee + #35 = Utf8 Hello , this is class Employee + #36 = Methodref #37.#39 // java/io/PrintStream.println:(Ljava/lang/String;)V + #37 = Class #38 // java/io/PrintStream + #38 = Utf8 java/io/PrintStream + #39 = NameAndType #40:#24 // println:(Ljava/lang/String;)V + #40 = Utf8 println + #41 = Utf8 main + #42 = Utf8 ([Ljava/lang/String;)V + #43 = String #44 // Andy + #44 = Utf8 Andy + #45 = Methodref #1.#46 // com/coderising/jvm/test/EmployeeV1."":(Ljava/lang/String;I)V + #46 = NameAndType #9:#10 // "":(Ljava/lang/String;I)V + #47 = Methodref #1.#48 // com/coderising/jvm/test/EmployeeV1.sayHello:()V + #48 = NameAndType #27:#14 // sayHello:()V + #49 = Utf8 args + #50 = Utf8 [Ljava/lang/String; + #51 = Utf8 p + #52 = Utf8 SourceFile + #53 = Utf8 EmployeeV1.java +{ + public com.coderising.jvm.test.EmployeeV1(java.lang.String, int); + descriptor: (Ljava/lang/String;I)V + flags: ACC_PUBLIC + Code: + stack=2, locals=3, args_size=3 + 0: aload_0 + 1: invokespecial #12 // Method java/lang/Object."":()V + 4: aload_0 + 5: aload_1 + 6: putfield #15 // Field name:Ljava/lang/String; + 9: aload_0 + 10: iload_2 + 11: putfield #17 // Field age:I + 14: return + LineNumberTable: + line 9: 0 + line 10: 4 + line 11: 9 + line 12: 14 + LocalVariableTable: + Start Length Slot Name Signature + 0 15 0 this Lcom/coderising/jvm/test/EmployeeV1; + 0 15 1 name Ljava/lang/String; + 0 15 2 age I + + public void setName(java.lang.String); + descriptor: (Ljava/lang/String;)V + flags: ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + 0: aload_0 + 1: aload_1 + 2: putfield #15 // Field name:Ljava/lang/String; + 5: return + LineNumberTable: + line 15: 0 + line 16: 5 + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/coderising/jvm/test/EmployeeV1; + 0 6 1 name Ljava/lang/String; + + public void setAge(int); + descriptor: (I)V + flags: ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + 0: aload_0 + 1: iload_1 + 2: putfield #17 // Field age:I + 5: return + LineNumberTable: + line 18: 0 + line 19: 5 + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/coderising/jvm/test/EmployeeV1; + 0 6 1 age I + + public void sayHello(); + descriptor: ()V + flags: ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + 0: getstatic #28 // Field java/lang/System.out:Ljava/io/PrintStream; + 3: ldc #34 // String Hello , this is class Employee + 5: invokevirtual #36 // Method java/io/PrintStream.println:(Ljava/lang/String;)V + 8: return + LineNumberTable: + line 21: 0 + line 22: 8 + LocalVariableTable: + Start Length Slot Name Signature + 0 9 0 this Lcom/coderising/jvm/test/EmployeeV1; + + public static void main(java.lang.String[]); + descriptor: ([Ljava/lang/String;)V + flags: ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=1 + 0: new #1 // class com/coderising/jvm/test/EmployeeV1 + 3: dup + 4: ldc #43 // String Andy + 6: bipush 29 + 8: invokespecial #45 // Method "":(Ljava/lang/String;I)V + 11: astore_1 + 12: aload_1 + 13: invokevirtual #47 // Method sayHello:()V + 16: return + LineNumberTable: + line 24: 0 + line 25: 12 + line 27: 16 + LocalVariableTable: + Start Length Slot Name Signature + 0 17 0 args [Ljava/lang/String; + 12 5 1 p Lcom/coderising/jvm/test/EmployeeV1; +} +SourceFile: "EmployeeV1.java" diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ClassFilePrinter.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..39553dd48c --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.print; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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 = "H:\\sourceCode\\coding2017\\group24\\494800949"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..baa0e8ead4 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,34 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.print; + + +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; + +import java.util.Formatter; + +public class ConstantPoolPrinter { + ConstantPool pool; + + ConstantPoolPrinter(ConstantPool pool) { + this.pool = pool; + } + + public void print() { + + System.out.println("Constant Pool:"); + + for (int i = 1; i <= (int)pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + Formatter formatter = new Formatter(System.out); + formatter.format("%5s", "#"+i); + constantInfo.accept(new SimpleVistor()); + } + } + + public static void main(String[] args) { +// Formatter f = new Formatter(System.out); +// f.format("%-15s %-5s %-10s\n", "Item", "Qty", "Price"); +// f.format("%-15s %-5s %-10s\n", "----", "----", "-----"); + + } +} diff --git a/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java b/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java index c919f0084f..1e202ed615 100644 --- a/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java +++ b/group24/494800949/src/test/java/com/coding/week6/exprNew/TokenParserTest.java @@ -12,7 +12,7 @@ public class TokenParserTest { @Test public void testParse() throws Exception { TokenParser tokenParser = new TokenParser(); - List tokens = tokenParser.parse("3*20+12*5-40/2"); + List tokens = tokenParser.parse("3* 20+1 2*5-40/2"); System.out.println(tokens); } } \ No newline at end of file From aca3a1737c7c74af154dfc99de62b252fe340be3 Mon Sep 17 00:00:00 2001 From: sdnb Date: Sun, 23 Apr 2017 23:02:49 +0800 Subject: [PATCH 114/151] =?UTF-8?q?jvm=E5=AD=97=E8=8A=82=E7=A0=81=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/coderising/jvm/attr/CodeAttr.java | 28 ++-- .../src/com/coderising/jvm/clz/ClassFile.java | 25 ++- .../src/com/coderising/jvm/cmd/BiPushCmd.java | 21 +++ .../coderising/jvm/cmd/ByteCodeCommand.java | 127 +++++++++++++++ .../com/coderising/jvm/cmd/CommandParser.java | 150 ++++++++++++++++++ .../com/coderising/jvm/cmd/GetFieldCmd.java | 21 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 20 +++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 22 +++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../src/com/coderising/jvm/cmd/LdcCmd.java | 30 ++++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 24 +++ .../com/coderising/jvm/cmd/OneOperandCmd.java | 27 ++++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 20 +++ .../com/coderising/jvm/cmd/TwoOperandCmd.java | 63 ++++++++ .../coderising/jvm/constant/ClassInfo.java | 7 +- .../coderising/jvm/constant/ConstantInfo.java | 13 +- .../coderising/jvm/constant/FieldRefInfo.java | 9 +- .../jvm/constant/MethodRefInfo.java | 7 +- .../jvm/constant/NameAndTypeInfo.java | 9 +- .../jvm/constant/NullConstantInfo.java | 6 +- .../coderising/jvm/constant/StringInfo.java | 7 +- .../com/coderising/jvm/constant/UTF8Info.java | 6 + .../jvm/loader/ByteCodeIterator.java | 9 ++ .../src/com/coderising/jvm/method/Method.java | 7 +- .../mini_jvm/test/ClassFileloaderTest.java | 79 +++++++++ 26 files changed, 753 insertions(+), 25 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/CommandParser.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java index ee04b856d7..b1685c4314 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -2,6 +2,8 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.ByteCodeCommand; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.CommandParser; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo { @@ -13,21 +15,23 @@ public String getCode() { return code; } - //private ByteCodeCommand[] cmds ; - //public ByteCodeCommand[] getCmds() { - // return cmds; - //} - private LineNumberTable lineNumTable; + 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*/) { + 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; + this.cmds = cmds; } public void setLineNumberTable(LineNumberTable t) { @@ -47,9 +51,9 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int maxStack = iter.readTwoBytesToInt(); int maxLocal = iter.readTwoBytesToInt(); int codeLen = iter.readFourBytesToInt(); - String code = iter.readBytesToString(codeLen); - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocal, codeLen, code); - + String code = iter.readBytesToHexString(codeLen); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocal, codeLen, code, cmds); //异常表长度 int exceptionTableLen = iter.readTwoBytesToInt(); if (exceptionTableLen > 0) { diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java index 047c65195f..6c88b9fff5 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -11,6 +11,7 @@ public class ClassFile { + private static final String MAIN_METHOD_NAME = "main"; private int minorVersion; private int majorVersion; @@ -79,13 +80,33 @@ public void print(){ System.out.println("Super Class Name:"+ getSuperClassName()); } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.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(); } + + public Method getMethod(String methodName, String paramAndReturnType){ + for (Method method : methods) { + String name = method.getClzFile().getConstantPool().getUTF8String(method.getNameIndex()); + if (methodName.equals(name)) { + return method; + } + } + + return null; + } + public Method getMainMethod(){ + for (Method method : methods) { + String name = method.getClzFile().getConstantPool().getUTF8String(method.getNameIndex()); + if (MAIN_METHOD_NAME.equals(name)) { + return method; + } + } + return null; + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..eb7dafa79d --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,21 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.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(); + } + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..b44d66c880 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,127 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + +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); +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..dd01d38872 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,150 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; + +import java.util.ArrayList; +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) { + CommandIterator cmdIter = new CommandIterator(codes); + List cmds = new ArrayList<>(); + //2ab7000c2a2bb5000f2a1cb50011b1 + while (cmdIter.hasNext()) { + String operCode = cmdIter.next2CharAsString().toUpperCase(); + switch (operCode) { + case bipush: + BiPushCmd cmd = new BiPushCmd(clzFile, operCode); + cmd.setOperand(cmdIter.next2CharAsInt()); + cmds.add(cmd); + break; + case getfield: + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, operCode); + getFieldCmd.setOprand1(cmdIter.next2CharAsInt()); + getFieldCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(getFieldCmd); + break; + case getstatic: + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, operCode); + getStaticFieldCmd.setOprand1(cmdIter.next2CharAsInt()); + getStaticFieldCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(getStaticFieldCmd); + break; + case invokespecial: + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, operCode); + invokeSpecialCmd.setOprand1(cmdIter.next2CharAsInt()); + invokeSpecialCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(invokeSpecialCmd); + break; + case invokevirtual: + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, operCode); + invokeVirtualCmd.setOprand1(cmdIter.next2CharAsInt()); + invokeVirtualCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(invokeVirtualCmd); + break; + case ldc: + LdcCmd ldcCmd = new LdcCmd(clzFile, operCode); + ldcCmd.setOperand(cmdIter.next2CharAsInt()); + cmds.add(ldcCmd); + break; + case new_object: + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, operCode); + newObjectCmd.setOprand1(cmdIter.next2CharAsInt()); + newObjectCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(newObjectCmd); + break; + case putfield: + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, operCode); + putFieldCmd.setOprand1(cmdIter.next2CharAsInt()); + putFieldCmd.setOprand2(cmdIter.next2CharAsInt()); + cmds.add(putFieldCmd); + break; + case astore_1: + case aload_0: + case aload_1: + case iload_1: + case iload_2: + case istore_1: + case voidreturn: + case dup: + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, operCode); + cmds.add(noOperandCmd); + break; + default: + throw new RuntimeException("this oper [ " +operCode+ " ]not impl yet"); + } + } + calcuateOffset(cmds); + return cmds.toArray(new ByteCodeCommand[cmds.size()]); + } + + 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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..5801068cb0 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,21 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e577d1b56c --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..2900bb2c60 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..ff7f0fdf14 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..abaeae3a9e --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..db90b82a35 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..3cd045f6d3 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,24 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..696764c3e7 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..6f6ecd0eb1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..78475ac911 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,63 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.cmd; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java index 227bb010a1..489e8c7c7c 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -15,10 +15,15 @@ public void setUtf8Index(int utf8Index) { public int getType() { return type; } - + public String getClassName() { int index = getUtf8Index(); UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java index e7c849ca59..7a9200f669 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -2,7 +2,6 @@ public abstract class ConstantInfo { public static final int UTF8_INFO = 1; - public static final int FLOAT_INFO = 4; public static final int CLASS_INFO = 7; public static final int STRING_INFO = 8; public static final int FIELD_INFO = 9; @@ -25,5 +24,15 @@ public ConstantPool getConstantPool() { 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); + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java index 1808a35c65..bca8e0b32b 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -11,7 +11,7 @@ public FieldRefInfo(ConstantPool pool) { public int getType() { return type; } - + public int getClassInfoIndex() { return classInfoIndex; } @@ -51,4 +51,11 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java index dc62d438e6..4664a79cf4 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -14,7 +14,12 @@ public MethodRefInfo(ConstantPool pool) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + public int getClassInfoIndex() { return classInfoIndex; } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java index b8b9da7353..f1c59a0d5e 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -25,8 +25,13 @@ public void setIndex2(int index2) { public int getType() { return type; } - - + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } + + public String getName(){ ConstantPool pool = this.getConstantPool(); UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java index bf19f681d8..16ec6a1e2f 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -9,5 +9,9 @@ public NullConstantInfo(){ public int getType() { return -1; } - + + @Override + public void accept(Visitor visitor) { + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java index 05a4afad6a..d18ac12305 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -10,7 +10,12 @@ public StringInfo(ConstantPool pool) { public int getType() { return type; } - + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + } + public int getIndex() { return index; } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java index 61f20ed8f1..81160db29e 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -16,6 +16,12 @@ public void setLength(int length) { public int getType() { return type; } + + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } + @Override public String toString() { return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java index 1fe59b5bdb..cf2db01a36 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -27,6 +27,15 @@ public String readBytesToString(int len) { } + public String readBytesToHexString(int len) { + byte[] bs = new byte[len]; + System.arraycopy(bytes, cursor, bs, 0, len); + String ret = Util.byteToHexString(bs); + cursor += len; + return ret; + } + + public int readTwoBytesToInt() { int ret = Util.bytes2Int(bytes, cursor, U2); cursor += U2; diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java index fd5734e6b6..b848e6b515 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java @@ -3,6 +3,7 @@ import com.coding.mini_jvm.src.com.coderising.jvm.attr.CodeAttr; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.ByteCodeCommand; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; public class Method { @@ -48,7 +49,6 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ int nameIndex = iter.readTwoBytesToInt(); int descIndex = iter.readTwoBytesToInt(); Method method = new Method(clzFile, accessFlag, nameIndex, descIndex); - System.out.println(clzFile.getConstantPool().getUTF8String(descIndex)); int attrCount = iter.readTwoBytesToInt(); if (attrCount > 1) throw new RuntimeException("other attrbute not impl yet"); @@ -58,9 +58,12 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); method.setCodeAttr(codeAttr); } else - throw new RuntimeException("not impl yet"); + throw new RuntimeException(" attribute[ " + attrNameIndex + " ] not impl yet"); } return method; } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } } diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java index 00812bcd80..b9561f243b 100644 --- a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java @@ -2,6 +2,10 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.BiPushCmd; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.ByteCodeCommand; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.OneOperandCmd; +import com.coding.mini_jvm.src.com.coderising.jvm.cmd.TwoOperandCmd; import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; @@ -244,4 +248,79 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } + + /***************************第四次jvm测试用例 **************************/ + @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 c866a88a113d1de1e00129d1d06ee84956423b4b Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Mon, 24 Apr 2017 09:46:58 +0800 Subject: [PATCH 115/151] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/basic/queue/CircleQueue.java | 5 --- .../src/com/coding/basic/queue/Josephus.java | 19 --------- .../com/coding/basic/queue/JosephusTest.java | 27 ------------- .../basic/queue/QueueWithTwoStacks.java | 40 ------------------- 4 files changed, 91 deletions(-) delete mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java delete mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java delete mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java delete mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java deleted file mode 100644 index 1ac659da3d..0000000000 --- a/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.coding.basic.queue; - -public class CircleQueue { - -} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java deleted file mode 100644 index d629d847f4..0000000000 --- a/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.coding.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/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java deleted file mode 100644 index 7d90318b51..0000000000 --- a/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.coding.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/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java deleted file mode 100644 index bbd4715ca6..0000000000 --- a/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.coding.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; - } - - - } - From e1798d0172d187a222c54cc0e582f6c38e008b9e Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Mon, 24 Apr 2017 09:52:19 +0800 Subject: [PATCH 116/151] refactor --- .../com/coding/basic/queue/CircleQueue.java | 30 +++- .../src/com/coding/basic/queue/Josephus.java | 24 +++- .../basic/queue/QueueWithTwoStacks.java | 26 +++- .../src/com/coding/basic/stack/Tail.java | 5 + .../basic/stack/expr/InfixToPostfix.java | 30 +++- .../com/coding/basic/queue/CircleQueue.java | 39 ++++++ .../src/com/coding/basic/queue/Josephus.java | 18 +++ .../com/coding/basic/queue/JosephusTest.java | 27 ++++ .../basic/queue/QueueWithTwoStacks.java | 47 +++++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 2 +- .../src/com/coderising/jvm/clz/ClassFile.java | 11 +- .../src/com/coderising/jvm/cmd/BiPushCmd.java | 15 +- .../coderising/jvm/cmd/ByteCodeCommand.java | 50 +++++-- .../com/coderising/jvm/cmd/CommandParser.java | 64 +++------ .../com/coderising/jvm/cmd/GetFieldCmd.java | 22 ++- .../coderising/jvm/cmd/GetStaticFieldCmd.java | 25 +++- .../coderising/jvm/cmd/InvokeSpecialCmd.java | 30 +++- .../coderising/jvm/cmd/InvokeVirtualCmd.java | 72 +++++++++- .../src/com/coderising/jvm/cmd/LdcCmd.java | 27 +++- .../com/coderising/jvm/cmd/NewObjectCmd.java | 26 +++- .../com/coderising/jvm/cmd/NoOperandCmd.java | 125 ++++++++++++++++- .../com/coderising/jvm/cmd/PutFieldCmd.java | 29 +++- .../com/coderising/jvm/cmd/TwoOperandCmd.java | 8 +- .../jvm/constant/MethodRefInfo.java | 3 + .../jvm/engine/ExecutionResult.java | 56 ++++++++ .../coderising/jvm/engine/ExecutorEngine.java | 83 +++++++++++ .../src/com/coderising/jvm/engine/Heap.java | 39 ++++++ .../com/coderising/jvm/engine/JavaObject.java | 71 ++++++++++ .../com/coderising/jvm/engine/MethodArea.java | 88 ++++++++++++ .../com/coderising/jvm/engine/MiniJVM.java | 28 ++++ .../coderising/jvm/engine/OperandStack.java | 26 ++++ .../com/coderising/jvm/engine/StackFrame.java | 131 ++++++++++++++++++ .../src/com/coderising/jvm/method/Method.java | 66 ++++++++- .../jvm/print/ClassFilePrinter.java | 2 +- .../jvm/test/ClassFileloaderTest.java | 2 +- .../com/coderising/jvm/test/MiniJVMTest.java | 28 ++++ 36 files changed, 1261 insertions(+), 114 deletions(-) create mode 100644 liuxin/data-structure/answer/src/com/coding/basic/stack/Tail.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutionResult.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutorEngine.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/Heap.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/JavaObject.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MethodArea.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MiniJVM.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/OperandStack.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/StackFrame.java create mode 100644 liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java index 1ac659da3d..b431db364f 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java @@ -1,5 +1,33 @@ package com.coding.basic.queue; -public class CircleQueue { +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; + } } diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/Josephus.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/Josephus.java index 29a9115535..4f33935f24 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/queue/Josephus.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/Josephus.java @@ -5,7 +5,7 @@ /** * 用Queue来实现Josephus问题 - * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 知道最后一个人留下来 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 * @author liuxin * */ @@ -13,7 +13,27 @@ public class Josephus { public static List execute(int n, int m){ - return null; + Queue queue = new Queue(); + for (int i = 0; i < n; i++){ + queue.enQueue(i); + } + + List result = new ArrayList(); + int i = 0; + + while (!queue.isEmpty()) { + + int x = queue.deQueue(); + + if (++i % m == 0){ + result.add(x); + } else{ + queue.enQueue(x); + } + } + + + return result; } } diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java index 4be68d6cbd..ed5a8dd98a 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -1,9 +1,10 @@ package com.coding.basic.queue; +import java.util.NoSuchElementException; import java.util.Stack; public class QueueWithTwoStacks { - private Stack stack1; + private Stack stack1; private Stack stack2; @@ -13,29 +14,42 @@ public QueueWithTwoStacks() { } - + private void moveStack1ToStack2() { + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + + } public boolean isEmpty() { - return false; + return stack1.isEmpty() && stack2.isEmpty(); } public int size() { - return -1; + return stack1.size() + stack2.size(); } public void enQueue(E item) { - + stack1.push(item); } public E deQueue() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + if (stack2.isEmpty()) { + moveStack1ToStack2(); + } + + return stack2.pop(); } + } diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/Tail.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/Tail.java new file mode 100644 index 0000000000..7f30ce55c8 --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/Tail.java @@ -0,0 +1,5 @@ +package com.coding.basic.stack; + +public class Tail { + +} diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java index 67ff350735..d52ec73bd3 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -1,13 +1,35 @@ package com.coding.basic.stack.expr; import java.util.List; +import java.util.Stack; public class InfixToPostfix { - + public static List convert(String expr) { - return null; + return null; + } + + public static void main(String[] args) { + Stack stack = new Stack(); + String expr = "1+((2+3)*4)-5"; + for(int i=0;i + */ +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; + } +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..6a3ea639b9 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,18 @@ +package com.coding.basic.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/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.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/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..cef19a8b59 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +package com.coding.basic.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; + } + + + + } + diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java index 03df78f541..279aea09b8 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java @@ -102,7 +102,7 @@ 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{ @@ -104,18 +140,6 @@ public String getOpCode() { 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){ @@ -124,5 +148,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java index 0410f9d061..f2ea2147fa 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java @@ -7,40 +7,7 @@ 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) { @@ -57,51 +24,58 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { while (iter.hasNext()) { String opCode = iter.next2CharAsString(); - if (new_object.equals(opCode)) { + if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.ldc.equals(opCode)) { LdcCmd cmd = new LdcCmd(clzFile, opCode); cmd.setOperand(iter.next2CharAsInt()); cmds.add(cmd); - } else if (bipush.equals(opCode)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.dup.equals(opCode) + || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) + || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) + || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) + || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode)) { NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); cmds.add(cmd); diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java index 2e6061edd2..1bf902da39 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -11,12 +15,24 @@ public GetFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } - + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + + } } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java index e6cf9d5960..9d42c7a75b 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -5,6 +5,10 @@ import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -15,9 +19,24 @@ public GetStaticFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 } - } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java index ac228d0e4d..f239957a4d 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -3,6 +3,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -13,11 +17,31 @@ public InvokeSpecialCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { + + return super.getOperandAsMethod(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + - return super.getOperandAsMethod(pool); } - } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java index c15d827797..ec9e508cbe 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -1,7 +1,13 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; + public class InvokeVirtualCmd extends TwoOperandCmd { @@ -11,12 +17,70 @@ public InvokeVirtualCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } - + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java index ffb66f811c..f00d1f07f3 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -12,9 +16,9 @@ public LdcCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + ConstantInfo info = getConstantInfo(this.getOperand()); String value = "TBD"; if(info instanceof StringInfo){ @@ -25,5 +29,22 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } - + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java index 33813b5d59..9cee0a1675 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -1,7 +1,12 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -10,10 +15,25 @@ public NewObjectCmd(ClassFile clzFile, String opCode){ } @Override - public String toString(ConstantPool pool) { + public String toString() { + + return super.getOperandAsClassInfo(); + } + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + - return super.getOperandAsClassInfo(pool); } - } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java index 56c28fefe2..0ef5fcc892 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -10,10 +14,129 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } public int getLength(){ diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java index 85bb369c19..63753d3c5d 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -1,7 +1,13 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -10,10 +16,29 @@ public PutFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java index 6c0cf53082..5af94b5f27 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -39,14 +39,14 @@ public int getIndex(){ return index; } - protected String getOperandAsClassInfo(ConstantPool pool){ + protected String getOperandAsClassInfo(){ 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){ + protected String getOperandAsMethod(){ int index = getIndex(); String codeTxt = getReadableCodeText(); ConstantInfo constInfo = this.getConstantInfo(index); @@ -54,7 +54,7 @@ protected String getOperandAsMethod(ConstantPool pool){ return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); } - protected String getOperandAsField(ConstantPool pool){ + protected String getOperandAsField(){ int index = getIndex(); String codeTxt = getReadableCodeText(); diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java index 036e6d9055..5701eca2e1 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -1,5 +1,8 @@ package com.coderising.jvm.constant; +import java.util.ArrayList; +import java.util.List; + public class MethodRefInfo extends ConstantInfo { private int type = ConstantInfo.METHOD_INFO; diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutionResult.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..8f6c51e52a --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutorEngine.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..79388c1e9c --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,83 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.empty()){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/Heap.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/JavaObject.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MethodArea.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..e71fd10ac1 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,88 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MiniJVM.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..443524cc5f --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i operands = new ArrayList(); + + public void push(JavaObject jo){ + operands.add(jo); + } + public JavaObject pop(){ + int index = size()-1; + JavaObject jo = (JavaObject)operands.get(index); + operands.remove(index); + return jo; + + } + public JavaObject top(){ + int index = size()-1; + return (JavaObject)operands.get(index); + } + public int size(){ + return operands.size(); + } +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/StackFrame.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..cfa31973fa --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/engine/StackFrame.java @@ -0,0 +1,131 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.method.Method; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/method/Method.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/method/Method.java index 71ab6ab053..3b141388ab 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/method/Method.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/method/Method.java @@ -2,9 +2,14 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.cmd.ByteCodeCommand; + +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; @@ -53,7 +58,7 @@ public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorInd -public String toString() { + public String toString() { ConstantPool pool = this.clzFile.getConstantPool(); StringBuilder buffer = new StringBuilder(); @@ -100,4 +105,63 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + private String getParamAndReturnType(){ + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/print/ClassFilePrinter.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/print/ClassFilePrinter.java index 14407bacbe..af5c9bec65 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/print/ClassFilePrinter.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -40,7 +40,7 @@ public void print(){ } public static void main(String[] args){ - String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); String className = "com.coderising.jvm.test.EmployeeV1"; diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/ClassFileloaderTest.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/ClassFileloaderTest.java index 5657310e0d..f1a996be49 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -31,7 +31,7 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; static String path2 = "C:\temp"; static ClassFile clzFile = null; diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..787c0d954d --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} From e062976461686c4bf830794425ae613414ef2011 Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Mon, 24 Apr 2017 10:00:49 +0800 Subject: [PATCH 117/151] refactor --- .../src/com/coderising/jvm/cmd/BiPushCmd.java | 8 ++ .../coderising/jvm/cmd/ByteCodeCommand.java | 4 +- .../com/coderising/jvm/cmd/GetFieldCmd.java | 8 ++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 8 ++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 8 ++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 7 ++ .../src/com/coderising/jvm/cmd/LdcCmd.java | 8 ++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 8 ++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 8 ++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 8 ++ .../jvm/engine/ExecutionResult.java | 56 +++++++++++ .../coderising/jvm/engine/ExecutorEngine.java | 35 +++++++ .../src/com/coderising/jvm/engine/Heap.java | 39 ++++++++ .../com/coderising/jvm/engine/JavaObject.java | 71 ++++++++++++++ .../com/coderising/jvm/engine/MethodArea.java | 68 +++++++++++++ .../com/coderising/jvm/engine/MiniJVM.java | 28 ++++++ .../com/coderising/jvm/engine/StackFrame.java | 95 +++++++++++++++++++ 17 files changed, 466 insertions(+), 1 deletion(-) create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutionResult.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutorEngine.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/Heap.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/JavaObject.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MethodArea.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MiniJVM.java create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/StackFrame.java diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java index cd0fbd4848..1f60641d2d 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -3,6 +3,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -17,6 +19,12 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java index a3abeacc82..e48d4e38f7 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -6,6 +6,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public abstract class ByteCodeCommand { @@ -124,5 +126,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java index 2e6061edd2..c771d535f7 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -16,6 +18,12 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java index e6cf9d5960..e6876c36bb 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -5,6 +5,8 @@ import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -20,4 +22,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java index ac228d0e4d..8d60e72341 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -3,6 +3,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -18,6 +20,12 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java index c15d827797..a1f2d1a1c6 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -2,6 +2,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -16,6 +18,11 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java index ffb66f811c..1669aa3900 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java @@ -4,6 +4,8 @@ import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -25,5 +27,11 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java index 33813b5d59..caa2609928 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -2,6 +2,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -15,5 +17,11 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java index 56c28fefe2..c3cda9b52e 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -2,6 +2,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -20,4 +22,10 @@ public int getLength(){ return 1; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java index 85bb369c19..dc31cf084d 100644 --- a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -2,6 +2,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -15,5 +17,11 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutionResult.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..8f6c51e52a --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutorEngine.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..5d6b582879 --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + + } + +} diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/Heap.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/JavaObject.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MethodArea.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..781e81acf1 --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,68 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MiniJVM.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..443524cc5f --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} From 76c37539a53433c8100cf924a2a82144cf519745 Mon Sep 17 00:00:00 2001 From: orajavac Date: Mon, 24 Apr 2017 10:07:46 +0800 Subject: [PATCH 118/151] 20170424_1007 jvm --- .../coding2017/jvm/attr/CodeAttr.java | 23 +++- .../jvm/attr/LocalVariableTable.java | 15 ++ .../coding2017/jvm/clz/ClassFile.java | 4 +- .../coding2017/jvm/cmd/BiPushCmd.java | 23 ++++ .../coding2017/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++++ .../coding2017/jvm/cmd/CommandParser.java | 85 ++++++++++++ .../coding2017/jvm/cmd/GetFieldCmd.java | 22 +++ .../coding2017/jvm/cmd/GetStaticFieldCmd.java | 23 ++++ .../coding2017/jvm/cmd/InvokeSpecialCmd.java | 23 ++++ .../coding2017/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../orajavac/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 | 6 + .../coding2017/jvm/constant/ConstantInfo.java | 11 ++ .../coding2017/jvm/constant/ConstantPool.java | 2 +- .../coding2017/jvm/constant/FieldRefInfo.java | 6 + .../jvm/constant/MethodRefInfo.java | 6 +- .../jvm/constant/NameAndTypeInfo.java | 8 +- .../jvm/constant/NullConstantInfo.java | 6 + .../coding2017/jvm/constant/StringInfo.java | 4 + .../coding2017/jvm/constant/UTF8Info.java | 5 +- .../orajavac/coding2017/jvm/field/Field.java | 20 ++- .../coding2017/jvm/method/Method.java | 18 ++- .../jvm/print/ClassFilePrinter.java | 53 ++++++++ .../jvm/print/ConstantPoolPrinter.java | 60 ++++++++ 29 files changed, 744 insertions(+), 13 deletions(-) create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/BiPushCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/ByteCodeCommand.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/CommandParser.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetFieldCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/LdcCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NewObjectCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NoOperandCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/OneOperandCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/PutFieldCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/TwoOperandCmd.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ClassFilePrinter.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ConstantPoolPrinter.java diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/attr/CodeAttr.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/attr/CodeAttr.java index 4fa025750d..acffda0f88 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/attr/CodeAttr.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.github.orajavac.coding2017.jvm.attr; import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; import com.github.orajavac.coding2017.jvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo{ @@ -13,10 +15,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; @@ -70,6 +72,19 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ } return null; } + + 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/562768642/src/com/github/orajavac/coding2017/jvm/cmd/CommandParser.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..7223cb7afc --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.github.orajavac.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(); + } + + } +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetFieldCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..acd1d7202f --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.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/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetStaticFieldCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..7bdc7ca76b --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ClassInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.FieldRefInfo; +import com.github.orajavac.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); + } + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeSpecialCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..f467b84f3f --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.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); + } + + + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeVirtualCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..f210141c66 --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.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); + } + + + + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/LdcCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..41f73494e7 --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ConstantInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.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; + + } + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NewObjectCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..52d280cc0b --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.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/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NoOperandCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..7a6781c152 --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.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/562768642/src/com/github/orajavac/coding2017/jvm/cmd/OneOperandCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..f9d005287f --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.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; + } + + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/PutFieldCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..1fd6b367e1 --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.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); + } + + +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/TwoOperandCmd.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..4deb99ecd2 --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.github.orajavac.coding2017.jvm.cmd; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ClassInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.FieldRefInfo; +import com.github.orajavac.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/562768642/src/com/github/orajavac/coding2017/jvm/constant/ClassInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ClassInfo.java index 730ca7663b..61dcdd9d3f 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ClassInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ClassInfo.java @@ -21,4 +21,10 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + + @Override + public void accept(Visistor visitor) { + visitor.visitClassInfo(this); + + } } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantInfo.java index 099f4012e0..37055df0a2 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantInfo.java @@ -26,4 +26,15 @@ public ConstantPool getConstantPool() { public ConstantInfo getConstantInfo(int index){ return this.constantPool.getConstantInfo(index); } + + public abstract void accept(Visistor visistor); + + public static interface Visistor{ + 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 visitUTF8(UTF8Info info); + } } diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantPool.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantPool.java index c1eef85f66..304e78f8ba 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantPool.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/ConstantPool.java @@ -22,7 +22,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/FieldRefInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/FieldRefInfo.java index f280244bed..c9a06f397d 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/FieldRefInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/FieldRefInfo.java @@ -51,4 +51,10 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visistor visitor) { + visitor.visitFieldRef(this); + + } } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/MethodRefInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/MethodRefInfo.java index f37c0f6452..6e53f8db5c 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/MethodRefInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/MethodRefInfo.java @@ -50,6 +50,10 @@ public String getParamAndReturnType(){ return typeInfo.getTypeInfo(); } - + @Override + public void accept(Visistor visitor) { + visitor.visitMethodRef(this); + + } } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NameAndTypeInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NameAndTypeInfo.java index 688e5f622f..0f25bb4ef6 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NameAndTypeInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NameAndTypeInfo.java @@ -42,4 +42,10 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } -} \ No newline at end of file + + @Override + public void accept(Visistor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NullConstantInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NullConstantInfo.java index af90d1dcf0..64eff24eef 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NullConstantInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/NullConstantInfo.java @@ -10,4 +10,10 @@ public int getType() { return -1; } + @Override + public void accept(Visistor visitor) { + + + } + } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/StringInfo.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/StringInfo.java index ecad1d633b..2224a46e73 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/StringInfo.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/StringInfo.java @@ -23,4 +23,8 @@ public String toString(){ return this.getConstantPool().getUTF8String(index); } + @Override + public void accept(Visistor visitor) { + visitor.visitString(this); + } } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/UTF8Info.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/UTF8Info.java index 5026756c57..bdceafe0f2 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/UTF8Info.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/constant/UTF8Info.java @@ -27,6 +27,9 @@ public void setValue(String value) { this.value = value; } - + @Override + public void accept(Visistor visitor) { + visitor.visitUTF8(this); + } } \ No newline at end of file diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/field/Field.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/field/Field.java index 8339ac98d4..40c8ad3a2c 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/field/Field.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/field/Field.java @@ -1,8 +1,10 @@ package com.github.orajavac.coding2017.jvm.field; import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.UTF8Info; import com.github.orajavac.coding2017.jvm.loader.ByteCodeIterator; + public class Field { private int accessFlag; private int nameIndex; @@ -20,15 +22,29 @@ public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool po 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(); - Field f = new Field(accessFlag,nameIndex,descIndex,pool); + //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/562768642/src/com/github/orajavac/coding2017/jvm/method/Method.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/method/Method.java index 5beb1fdf12..6f43647396 100644 --- a/group02/562768642/src/com/github/orajavac/coding2017/jvm/method/Method.java +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/method/Method.java @@ -3,6 +3,8 @@ import com.github.orajavac.coding2017.jvm.attr.AttributeInfo; import com.github.orajavac.coding2017.jvm.attr.CodeAttr; import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.UTF8Info; import com.github.orajavac.coding2017.jvm.field.Field; import com.github.orajavac.coding2017.jvm.loader.ByteCodeIterator; @@ -42,7 +44,21 @@ public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorInd 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(); + } diff --git a/group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ClassFilePrinter.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..c46c21056d --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ClassFilePrinter.java @@ -0,0 +1,53 @@ +package com.github.orajavac.coding2017.jvm.print; + +import com.github.orajavac.coding2017.jvm.clz.ClassFile; +import com.github.orajavac.coding2017.jvm.constant.ClassInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.FieldRefInfo; +import com.github.orajavac.coding2017.jvm.constant.MethodRefInfo; +import com.github.orajavac.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.orajavac.coding2017.jvm.constant.StringInfo; +import com.github.orajavac.coding2017.jvm.constant.UTF8Info; +import com.github.orajavac.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 = "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/562768642/src/com/github/orajavac/coding2017/jvm/print/ConstantPoolPrinter.java b/group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..6c4a3915bd --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,60 @@ + package com.github.orajavac.coding2017.jvm.print; + +import com.github.orajavac.coding2017.jvm.constant.ClassInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantInfo; +import com.github.orajavac.coding2017.jvm.constant.ConstantPool; +import com.github.orajavac.coding2017.jvm.constant.FieldRefInfo; +import com.github.orajavac.coding2017.jvm.constant.MethodRefInfo; +import com.github.orajavac.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.orajavac.coding2017.jvm.constant.StringInfo; +import com.github.orajavac.coding2017.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visistor visistor = new ConstantInfo.Visistor(){ + public void visitString(StringInfo info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + } + + public void visitClassInfo(ClassInfo info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()).append(" ") + .append(info.getClassName()); + } + + public void visitFieldRef(FieldRefInfo info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("FiledRef #").append(info.getClassInfoIndex()).append(" ") + .append(info.getNameAndTypeIndex()); + } + + public void visitMethodRef(MethodRefInfo info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(" ").append(info.getParamAndReturnType()); + } + + public void visitNameAndType(NameAndTypeInfo info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(" ").append(info.getIndex2()); + } + + public void visitUTF8(UTF8Info info){ + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 #").append(info.getValue()); + } + }; + + for (int i=0;i Date: Mon, 24 Apr 2017 11:23:13 +0800 Subject: [PATCH 119/151] =?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 120/151] 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 121/151] 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; + } + +} From 699b8c225ed499e2f6203a1b42e8ea231f55cc54 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Mon, 24 Apr 2017 16:10:49 +0800 Subject: [PATCH 122/151] CircleQueue finished --- .../com/donaldy/basic/queue/CircleQueue.java | 74 +++++++++++++++++++ .../donaldy/basic/queue/CircleQueueTest.java | 33 +++++++++ .../src/com/donaldy/basic/queue/Josephus.java | 18 +++++ .../com/donaldy/basic/queue/JosephusTest.java | 27 +++++++ .../src/com/donaldy/basic/queue/Queue.java | 62 ++++++++++++++++ .../basic/queue/QueueWithTwoStacks.java | 47 ++++++++++++ 6 files changed, 261 insertions(+) create mode 100644 group24/448641125/src/com/donaldy/basic/queue/CircleQueue.java create mode 100644 group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java create mode 100644 group24/448641125/src/com/donaldy/basic/queue/Josephus.java create mode 100644 group24/448641125/src/com/donaldy/basic/queue/JosephusTest.java create mode 100644 group24/448641125/src/com/donaldy/basic/queue/Queue.java create mode 100644 group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java diff --git a/group24/448641125/src/com/donaldy/basic/queue/CircleQueue.java b/group24/448641125/src/com/donaldy/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..fbe5cdc6c8 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/CircleQueue.java @@ -0,0 +1,74 @@ +package com.donaldy.basic.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; + //元素个数 + private int size = 0; + + public boolean isEmpty() { + + return this.size == 0; + + } + + public int size() { + return this.size; + } + + + + public void enQueue(E data) { + + if (this.size == DEFAULT_SIZE) { + throw new IndexOutOfBoundsException("size() : " + this.size()); + } + + this.elementData[this.rear] = data; + + this.rear = (this.rear + 1) % DEFAULT_SIZE; + + this.size ++; + + } + + public E deQueue() { + + if (this.isEmpty()) { + throw new IndexOutOfBoundsException("size() : " + this.size()); + } + + E oldElement = (E) this.elementData[this.front]; + + this.elementData[this.front] = null; + + this.front = (this.front + 1) % DEFAULT_SIZE; + + this.size --; + + return oldElement; + } + + public E getElement(int index) { + + if (index < 0 || index >= DEFAULT_SIZE) { + throw new IndexOutOfBoundsException("index : " + index); + } + + return (E)this.elementData[index]; + } +} diff --git a/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java b/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..9489f917ca --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java @@ -0,0 +1,33 @@ +package com.donaldy.basic.queue; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/4/24. + */ +public class CircleQueueTest { + + @Test + public void test() { + CircleQueue cirQueue = new CircleQueue<>(); + + for (int i = 1; i <= 10; ++i) { + cirQueue.enQueue(i); + } + + Assert.assertEquals(10, cirQueue.size()); + + for (int i = 0; i < 10; ++i) { + Assert.assertEquals(i + 1, (int)cirQueue.getElement(i)); + } + + + for (int i = 0; i <= 5; ++i) { + Assert.assertEquals(i + 1, (int)cirQueue.deQueue()); + } + + Assert.assertEquals(4, cirQueue.size()); + + } +} diff --git a/group24/448641125/src/com/donaldy/basic/queue/Josephus.java b/group24/448641125/src/com/donaldy/basic/queue/Josephus.java new file mode 100644 index 0000000000..237f562234 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/Josephus.java @@ -0,0 +1,18 @@ +package com.donaldy.basic.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/group24/448641125/src/com/donaldy/basic/queue/JosephusTest.java b/group24/448641125/src/com/donaldy/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..dad206e942 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/basic/queue/Queue.java b/group24/448641125/src/com/donaldy/basic/queue/Queue.java new file mode 100644 index 0000000000..d504367907 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/Queue.java @@ -0,0 +1,62 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..99ca88525f --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +package com.donaldy.basic.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; + } + + + + } + From 6e777c5ace01fbb56a12cb9e2f84b5eb9c74807c Mon Sep 17 00:00:00 2001 From: gongxun Date: Mon, 24 Apr 2017 18:40:06 +0800 Subject: [PATCH 123/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A04=E6=9C=8823=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.16/cmd/BiPushCmd.java | 9 ++ .../785396327/4.16/cmd/ByteCodeCommand.java | 4 +- group17/785396327/4.16/cmd/GetFieldCmd.java | 7 ++ .../785396327/4.16/cmd/GetStaticFieldCmd.java | 7 ++ .../785396327/4.16/cmd/InvokeSpecialCmd.java | 7 ++ .../785396327/4.16/cmd/InvokeVirtualCmd.java | 7 ++ group17/785396327/4.16/cmd/LdcCmd.java | 7 ++ group17/785396327/4.16/cmd/NewObjectCmd.java | 9 +- group17/785396327/4.16/cmd/NoOperandCmd.java | 6 ++ group17/785396327/4.16/cmd/PutFieldCmd.java | 7 ++ .../4.23/engine/ExecutionResult.java | 55 +++++++++++ .../785396327/4.23/engine/ExecutorEngine.java | 29 ++++++ .../785396327/4.23/engine/FrameResult.java | 7 ++ group17/785396327/4.23/engine/Heap.java | 41 ++++++++ group17/785396327/4.23/engine/JavaObject.java | 73 ++++++++++++++ group17/785396327/4.23/engine/MethodArea.java | 70 ++++++++++++++ group17/785396327/4.23/engine/MiniJVM.java | 29 ++++++ group17/785396327/4.23/engine/StackFrame.java | 95 +++++++++++++++++++ group17/785396327/4.23/queue/CircleQueue.java | 36 +++++++ group17/785396327/4.23/queue/Josephus.java | 15 +++ .../785396327/4.23/queue/JosephusTest.java | 26 +++++ .../4.23/queue/QueueWithTwoStacks.java | 42 ++++++++ 22 files changed, 586 insertions(+), 2 deletions(-) create mode 100644 group17/785396327/4.23/engine/ExecutionResult.java create mode 100644 group17/785396327/4.23/engine/ExecutorEngine.java create mode 100644 group17/785396327/4.23/engine/FrameResult.java create mode 100644 group17/785396327/4.23/engine/Heap.java create mode 100644 group17/785396327/4.23/engine/JavaObject.java create mode 100644 group17/785396327/4.23/engine/MethodArea.java create mode 100644 group17/785396327/4.23/engine/MiniJVM.java create mode 100644 group17/785396327/4.23/engine/StackFrame.java create mode 100644 group17/785396327/4.23/queue/CircleQueue.java create mode 100644 group17/785396327/4.23/queue/Josephus.java create mode 100644 group17/785396327/4.23/queue/JosephusTest.java create mode 100644 group17/785396327/4.23/queue/QueueWithTwoStacks.java diff --git a/group17/785396327/4.16/cmd/BiPushCmd.java b/group17/785396327/4.16/cmd/BiPushCmd.java index 9353ea0412..79da192e67 100644 --- a/group17/785396327/4.16/cmd/BiPushCmd.java +++ b/group17/785396327/4.16/cmd/BiPushCmd.java @@ -2,6 +2,9 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.ExecutionResult; +import engine.FrameResult; +import engine.StackFrame; /** * Created by william on 2017/4/17. @@ -17,4 +20,10 @@ public String toString(ConstantPool pool) { return this.getOffset() + ": " + this.getOpCode() + " " + this.getReadableCodeText() + " " + this.getOperand(); } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } + } diff --git a/group17/785396327/4.16/cmd/ByteCodeCommand.java b/group17/785396327/4.16/cmd/ByteCodeCommand.java index f10bfa21d3..66abdd0865 100644 --- a/group17/785396327/4.16/cmd/ByteCodeCommand.java +++ b/group17/785396327/4.16/cmd/ByteCodeCommand.java @@ -3,6 +3,8 @@ import clz.ClassFile; import constant.ConstantInfo; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; import java.util.HashMap; import java.util.Map; @@ -125,5 +127,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame, FrameResult result); } diff --git a/group17/785396327/4.16/cmd/GetFieldCmd.java b/group17/785396327/4.16/cmd/GetFieldCmd.java index c7307abf56..59425edc38 100644 --- a/group17/785396327/4.16/cmd/GetFieldCmd.java +++ b/group17/785396327/4.16/cmd/GetFieldCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by william on 2017/4/17. @@ -17,4 +19,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, FrameResult result) { + + } + } diff --git a/group17/785396327/4.16/cmd/GetStaticFieldCmd.java b/group17/785396327/4.16/cmd/GetStaticFieldCmd.java index 37ca3c7195..c21e230306 100644 --- a/group17/785396327/4.16/cmd/GetStaticFieldCmd.java +++ b/group17/785396327/4.16/cmd/GetStaticFieldCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -17,4 +19,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } } diff --git a/group17/785396327/4.16/cmd/InvokeSpecialCmd.java b/group17/785396327/4.16/cmd/InvokeSpecialCmd.java index 80af63e860..3dd0c7b70e 100644 --- a/group17/785396327/4.16/cmd/InvokeSpecialCmd.java +++ b/group17/785396327/4.16/cmd/InvokeSpecialCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -17,4 +19,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } } diff --git a/group17/785396327/4.16/cmd/InvokeVirtualCmd.java b/group17/785396327/4.16/cmd/InvokeVirtualCmd.java index 631e743c5f..254534a78f 100644 --- a/group17/785396327/4.16/cmd/InvokeVirtualCmd.java +++ b/group17/785396327/4.16/cmd/InvokeVirtualCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -16,4 +18,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } } diff --git a/group17/785396327/4.16/cmd/LdcCmd.java b/group17/785396327/4.16/cmd/LdcCmd.java index 183a4010de..ce1f34df3c 100644 --- a/group17/785396327/4.16/cmd/LdcCmd.java +++ b/group17/785396327/4.16/cmd/LdcCmd.java @@ -4,6 +4,8 @@ import constant.ConstantInfo; import constant.ConstantPool; import constant.StringInfo; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -27,4 +29,9 @@ public String toString(ConstantPool pool) { return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " " + value; } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } } diff --git a/group17/785396327/4.16/cmd/NewObjectCmd.java b/group17/785396327/4.16/cmd/NewObjectCmd.java index 6cd609aeb4..d284274f0b 100644 --- a/group17/785396327/4.16/cmd/NewObjectCmd.java +++ b/group17/785396327/4.16/cmd/NewObjectCmd.java @@ -2,9 +2,11 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** - * Created by IBM on 2017/4/17. + * Created by gongxun on 2017/4/17. */ public class NewObjectCmd extends TwoOperandCmd { public NewObjectCmd(ClassFile clzFile, String opCode){ @@ -17,4 +19,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } + @Override + public void execute(StackFrame frame, FrameResult result) { + + } + } diff --git a/group17/785396327/4.16/cmd/NoOperandCmd.java b/group17/785396327/4.16/cmd/NoOperandCmd.java index 7797d5218e..828ae2094e 100644 --- a/group17/785396327/4.16/cmd/NoOperandCmd.java +++ b/group17/785396327/4.16/cmd/NoOperandCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -16,6 +18,10 @@ public String toString(ConstantPool pool) { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } + @Override + public void execute(StackFrame frame, FrameResult result) { + + } public int getLength(){ diff --git a/group17/785396327/4.16/cmd/PutFieldCmd.java b/group17/785396327/4.16/cmd/PutFieldCmd.java index 07c88273cc..f0994739a0 100644 --- a/group17/785396327/4.16/cmd/PutFieldCmd.java +++ b/group17/785396327/4.16/cmd/PutFieldCmd.java @@ -2,6 +2,8 @@ import clz.ClassFile; import constant.ConstantPool; +import engine.FrameResult; +import engine.StackFrame; /** * Created by IBM on 2017/4/17. @@ -16,4 +18,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + + @Override + public void execute(StackFrame frame, FrameResult result) { + + } } diff --git a/group17/785396327/4.23/engine/ExecutionResult.java b/group17/785396327/4.23/engine/ExecutionResult.java new file mode 100644 index 0000000000..4dcb84fb62 --- /dev/null +++ b/group17/785396327/4.23/engine/ExecutionResult.java @@ -0,0 +1,55 @@ +package engine; + +import method.Method; + +/** + * Created by gongxun on 2017/4/24. + */ +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + +} diff --git a/group17/785396327/4.23/engine/ExecutorEngine.java b/group17/785396327/4.23/engine/ExecutorEngine.java new file mode 100644 index 0000000000..729d7c12be --- /dev/null +++ b/group17/785396327/4.23/engine/ExecutorEngine.java @@ -0,0 +1,29 @@ +package engine; + +import method.Method; +import stack.Stack; + +/** + * Created by gongxun on 2017/4/24. + */ +public class ExecutorEngine { + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + + } +} diff --git a/group17/785396327/4.23/engine/FrameResult.java b/group17/785396327/4.23/engine/FrameResult.java new file mode 100644 index 0000000000..7630e0a37a --- /dev/null +++ b/group17/785396327/4.23/engine/FrameResult.java @@ -0,0 +1,7 @@ +package engine; + +/** + * Created by gongxun on 2017/4/24. + */ +public class FrameResult { +} diff --git a/group17/785396327/4.23/engine/Heap.java b/group17/785396327/4.23/engine/Heap.java new file mode 100644 index 0000000000..dc7c2ccf6f --- /dev/null +++ b/group17/785396327/4.23/engine/Heap.java @@ -0,0 +1,41 @@ +package engine; + +/** + * Created by gongxun on 2017/4/24. + */ +public class Heap { + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group17/785396327/4.23/engine/JavaObject.java b/group17/785396327/4.23/engine/JavaObject.java new file mode 100644 index 0000000000..efd8adf5df --- /dev/null +++ b/group17/785396327/4.23/engine/JavaObject.java @@ -0,0 +1,73 @@ +package engine; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by gongxun on 2017/4/24. + */ +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } +} diff --git a/group17/785396327/4.23/engine/MethodArea.java b/group17/785396327/4.23/engine/MethodArea.java new file mode 100644 index 0000000000..3ede83b192 --- /dev/null +++ b/group17/785396327/4.23/engine/MethodArea.java @@ -0,0 +1,70 @@ +package engine; + +import clz.ClassFile; +import constant.MethodRefInfo; +import jvm_1.ClassFileLoader; +import method.Method; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by gongxun on 2017/4/24. + */ +public class MethodArea { + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/group17/785396327/4.23/engine/MiniJVM.java b/group17/785396327/4.23/engine/MiniJVM.java new file mode 100644 index 0000000000..19094eee23 --- /dev/null +++ b/group17/785396327/4.23/engine/MiniJVM.java @@ -0,0 +1,29 @@ +package engine; + +import jvm_1.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Created by gongxun on 2017/4/24. + */ +public class MiniJVM { + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException { + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } +} diff --git a/group17/785396327/4.23/queue/CircleQueue.java b/group17/785396327/4.23/queue/CircleQueue.java new file mode 100644 index 0000000000..228bf1aba1 --- /dev/null +++ b/group17/785396327/4.23/queue/CircleQueue.java @@ -0,0 +1,36 @@ +package queue; + +/** + * Created by gongxun on 2017/4/24. + * 用数组实现循环队列 + */ +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; + } +} diff --git a/group17/785396327/4.23/queue/Josephus.java b/group17/785396327/4.23/queue/Josephus.java new file mode 100644 index 0000000000..7d85d94a01 --- /dev/null +++ b/group17/785396327/4.23/queue/Josephus.java @@ -0,0 +1,15 @@ +package queue; + +import java.util.List; + +/** + * Created by gongxun on 2017/4/24. + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + */ +public class Josephus { + public static List execute(int n, int m) { + return null; + } +} diff --git a/group17/785396327/4.23/queue/JosephusTest.java b/group17/785396327/4.23/queue/JosephusTest.java new file mode 100644 index 0000000000..ba502d0ffb --- /dev/null +++ b/group17/785396327/4.23/queue/JosephusTest.java @@ -0,0 +1,26 @@ +package queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/24. + */ +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/group17/785396327/4.23/queue/QueueWithTwoStacks.java b/group17/785396327/4.23/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..7f38a9c20c --- /dev/null +++ b/group17/785396327/4.23/queue/QueueWithTwoStacks.java @@ -0,0 +1,42 @@ +package queue; + +import stack.Stack; + +/** + * Created by gongxun on 2017/4/24. + */ +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; + } + + +} From 3e956cb57f9dfff55b8860d7a3b3b03ba63889b5 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Mon, 24 Apr 2017 19:58:54 +0800 Subject: [PATCH 124/151] datastructure finished --- .../donaldy/basic/queue/CircleQueueTest.java | 2 + .../src/com/donaldy/basic/queue/Josephus.java | 50 +++++++++++++++++-- .../basic/queue/QueueWithTwoStacks.java | 45 ++++++++++++----- .../basic/queue/QueueWithTwoStacksTest.java | 23 +++++++++ 4 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacksTest.java diff --git a/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java b/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java index 9489f917ca..f6516c7743 100644 --- a/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java +++ b/group24/448641125/src/com/donaldy/basic/queue/CircleQueueTest.java @@ -3,6 +3,8 @@ import org.junit.Assert; import org.junit.Test; + + /** * Created by DonaldY on 2017/4/24. */ diff --git a/group24/448641125/src/com/donaldy/basic/queue/Josephus.java b/group24/448641125/src/com/donaldy/basic/queue/Josephus.java index 237f562234..9d3d588148 100644 --- a/group24/448641125/src/com/donaldy/basic/queue/Josephus.java +++ b/group24/448641125/src/com/donaldy/basic/queue/Josephus.java @@ -1,18 +1,62 @@ package com.donaldy.basic.queue; +import java.util.ArrayList; import java.util.List; /** * 用Queue来实现Josephus问题 - * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * 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){ + + List killList = new ArrayList(); + + //用于存储 + Queue queue1 = new Queue<>(); + //用于操作 + Queue queue2 = new Queue<>(); + + for (int i = 0; i < n; ++i) { + + queue1.enQueue(i); + + } + + int cnt = 1; + + while (true) { + + if (queue1.size() < m) { + break; + } + + if (cnt % m == 0) { + + killList.add(queue1.deQueue()); + + } else { + + queue1.enQueue(queue1.deQueue()); + + } + + cnt ++; + + } + + while (!queue1.isEmpty()) { + killList.add(queue1.deQueue()); + } + + + return killList; } } diff --git a/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java index 99ca88525f..98496b3e77 100644 --- a/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java +++ b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacks.java @@ -9,38 +9,59 @@ * @param */ public class QueueWithTwoStacks { - private Stack stack1; - private Stack stack2; - + //用于存储 + private Stack stack1; + //用于操作 + private Stack stack2; + public QueueWithTwoStacks() { stack1 = new Stack(); stack2 = new Stack(); } - - public boolean isEmpty() { - return false; + + return this.stack1.isEmpty(); + } - public int size() { - return -1; - } + return this.stack1.size(); + + } public void enQueue(E item) { - + this.stack1.push(item); } public E deQueue() { - return null; - } + if (this.size() <= 0) { + throw new IndexOutOfBoundsException("size : " + this.size()); + } + + while (!this.stack1.isEmpty()) { + + this.stack2.push(this.stack1.pop()); + + } + + E oldElement = this.stack2.pop(); + + while (!this.stack2.isEmpty()) { + + this.stack1.push(this.stack2.pop()); + + } + + return oldElement; + + } } diff --git a/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacksTest.java b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..21dcd53b85 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,23 @@ +package com.donaldy.basic.queue; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/4/24. + */ +public class QueueWithTwoStacksTest { + + @Test + public void test() { + QueueWithTwoStacks qwStack = new QueueWithTwoStacks(); + + for (int i = 1; i <= 5; ++i) { + qwStack.enQueue(i); + } + + for (int i = 1; i <= 5; ++i) { + Assert.assertEquals(i, (int)qwStack.deQueue()); + } + } +} From 1c826c118fccb1433c1a991f9ec8f5e3a472dc1d Mon Sep 17 00:00:00 2001 From: GordenChow <513274874@qq.com> Date: Mon, 24 Apr 2017 19:59:37 +0800 Subject: [PATCH 125/151] =?UTF-8?q?JVM=E7=AC=AC=E4=BA=94=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JVM第五周作业,修改以往作业bug --- .../src/com/coding/basic/Stack.java | 65 --------- .../coding/basic/{ => array}/ArrayList.java | 6 +- .../com/coding/basic/{ => array}/List.java | 2 +- .../com/coding/basic/linklist/LinkedList.java | 2 +- .../src/com/coding/basic/stack/Stack.java | 4 +- .../basic/stack/expr/InfixExprTest.java | 9 ++ .../basic/stack/expr/InfixToPostfix.java | 57 ++++++++ .../coding/basic/stack/expr/PostfixExpr.java | 51 +++++++ .../basic/stack/expr/PostfixExprTest.java | 41 ++++++ .../coding/basic/stack/expr/PrefixExpr.java | 18 +++ .../basic/stack/expr/PrefixExprTest.java | 45 ++++++ .../com/coding/basic/stack/expr/Token.java | 50 +++++++ .../coding/basic/stack/expr/TokenParser.java | 57 ++++++++ .../basic/stack/expr/TokenParserTest.java | 41 ++++++ .../src/com/coderising/jvm/attr/CodeAttr.java | 22 ++- .../coderising/jvm/attr/LineNumberTable.java | 12 ++ .../jvm/attr/LocalVariableTable.java | 15 ++ .../src/com/coderising/jvm/clz/ClassFile.java | 20 ++- .../src/com/coderising/jvm/cmd/BiPushCmd.java | 23 ++++ .../coderising/jvm/cmd/ByteCodeCommand.java | 128 ++++++++++++++++++ .../com/coderising/jvm/cmd/CommandParser.java | 85 ++++++++++++ .../com/coderising/jvm/cmd/GetFieldCmd.java | 22 +++ .../coderising/jvm/cmd/GetStaticFieldCmd.java | 23 ++++ .../coderising/jvm/cmd/InvokeSpecialCmd.java | 23 ++++ .../coderising/jvm/cmd/InvokeVirtualCmd.java | 22 +++ .../src/com/coderising/jvm/cmd/LdcCmd.java | 29 ++++ .../com/coderising/jvm/cmd/NewObjectCmd.java | 19 +++ .../com/coderising/jvm/cmd/NoOperandCmd.java | 23 ++++ .../com/coderising/jvm/cmd/OneOperandCmd.java | 27 ++++ .../com/coderising/jvm/cmd/PutFieldCmd.java | 19 +++ .../com/coderising/jvm/cmd/TwoOperandCmd.java | 67 +++++++++ .../coderising/jvm/constant/ClassInfo.java | 4 + .../coderising/jvm/constant/ConstantInfo.java | 11 ++ .../coderising/jvm/constant/FieldRefInfo.java | 4 + .../jvm/constant/MethodRefInfo.java | 5 + .../jvm/constant/NameAndTypeInfo.java | 6 + .../jvm/constant/NullConstantInfo.java | 4 + .../coderising/jvm/constant/StringInfo.java | 6 + .../com/coderising/jvm/constant/UTF8Info.java | 5 + .../src/com/coderising/jvm/method/Method.java | 22 +++ .../jvm/print/ClassFilePrinter.java | 45 ++++++ .../jvm/print/ConstantPoolPrinter.java | 83 ++++++++++++ .../jvm/test/ClassFileloaderTest.java | 77 +++++++++++ 43 files changed, 1220 insertions(+), 79 deletions(-) delete mode 100644 group27/513274874/data-structure/src/com/coding/basic/Stack.java rename group27/513274874/data-structure/src/com/coding/basic/{ => array}/ArrayList.java (96%) rename group27/513274874/data-structure/src/com/coding/basic/{ => array}/List.java (81%) create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/Token.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParser.java create mode 100644 group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java create mode 100644 group27/513274874/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java diff --git a/group27/513274874/data-structure/src/com/coding/basic/Stack.java b/group27/513274874/data-structure/src/com/coding/basic/Stack.java deleted file mode 100644 index 034e4c7215..0000000000 --- a/group27/513274874/data-structure/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,65 +0,0 @@ - -package com.coding.basic; - -/** - * author zhougd 20170306 - * - */ -public class Stack { - private List elementData = new ArrayList(); - - - public Stack() { - } - - /** - * 入栈 - * @param o - */ - public void push(Object o){ - elementData.add(o); - } - - /** - * 出栈 - * @return - */ - public Object pop(){ - if(this.isEmpty()){ - throw new IndexOutOfBoundsException("stack is empty!"); - } - Object element = elementData.get(size()-1); - elementData.remove(size()-1); - return element; - } - - /** - * 查看栈顶元素 - * @return Object - */ - public Object peek(){ - if(this.isEmpty()){ - throw new IndexOutOfBoundsException("stack is empty!"); - } - Object element = elementData.get(size()-1); - return element; - } - - /** - * 查看栈是否为空 - * @return boolean - */ - public boolean isEmpty(){ - - return elementData == null || elementData.size()<=0; - - } - - /** - * 获取栈大小 - * @return - */ - public int size(){ - return elementData.size(); - } -} \ No newline at end of file diff --git a/group27/513274874/data-structure/src/com/coding/basic/ArrayList.java b/group27/513274874/data-structure/src/com/coding/basic/array/ArrayList.java similarity index 96% rename from group27/513274874/data-structure/src/com/coding/basic/ArrayList.java rename to group27/513274874/data-structure/src/com/coding/basic/array/ArrayList.java index 9e55e92529..7d6d7a08f2 100644 --- a/group27/513274874/data-structure/src/com/coding/basic/ArrayList.java +++ b/group27/513274874/data-structure/src/com/coding/basic/array/ArrayList.java @@ -1,5 +1,7 @@ -package com.coding.basic; +package com.coding.basic.array; + +import com.coding.basic.Iterator; import java.util.Arrays; @@ -78,7 +80,7 @@ public Object remove(int index) { } public int size() { - return this.size + 1; + return this.size; } public Iterator iterator() { diff --git a/group27/513274874/data-structure/src/com/coding/basic/List.java b/group27/513274874/data-structure/src/com/coding/basic/array/List.java similarity index 81% rename from group27/513274874/data-structure/src/com/coding/basic/List.java rename to group27/513274874/data-structure/src/com/coding/basic/array/List.java index 396b1f6416..2a07c92d6e 100644 --- a/group27/513274874/data-structure/src/com/coding/basic/List.java +++ b/group27/513274874/data-structure/src/com/coding/basic/array/List.java @@ -1,4 +1,4 @@ -package com.coding.basic; +package com.coding.basic.array; public interface List { public void add(Object o); diff --git a/group27/513274874/data-structure/src/com/coding/basic/linklist/LinkedList.java b/group27/513274874/data-structure/src/com/coding/basic/linklist/LinkedList.java index e6d400f483..245affee80 100644 --- a/group27/513274874/data-structure/src/com/coding/basic/linklist/LinkedList.java +++ b/group27/513274874/data-structure/src/com/coding/basic/linklist/LinkedList.java @@ -2,7 +2,7 @@ package com.coding.basic.linklist; import com.coding.basic.Iterator; -import com.coding.basic.List; +import com.coding.basic.array.List; import java.util.NoSuchElementException; diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java b/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java index 4a0980079b..3b8a9eeb5a 100644 --- a/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java @@ -1,7 +1,8 @@ package com.coding.basic.stack; -import com.coding.basic.List; + +import com.coding.basic.array.List; import com.coding.basic.array.ArrayList; /** @@ -20,6 +21,7 @@ public Stack() { * @param o */ public void push(Object o){ + elementData.add(o); } diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java index 343683f11a..ddb1130398 100644 --- a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -42,7 +42,16 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } } + @Test + public void testConert(){ + new InfixToPostfix().convert("2*3*4+5"); + } + } diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..55eb061ce0 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +import java.util.ArrayList; +import java.util.List; + +public class InfixToPostfix { + private Stack operStack = new Stack(); + + public List convert(String expr) { + + List infixList = TokenParser.parse(expr); + List postfixList = new ArrayList<>(); + int i = 0; + while(i < infixList.size()){ + Token token = infixList.get(i); + if(token.isNumber()){ + //operand + postfixList.add(token); + + }else{ + //operator + if(operStack.isEmpty()) { + operStack.push(token); + i++; + continue; + } + + Token topToken = (Token)operStack.pop(); + + if(token.hasHigherPriority(topToken)){ + //the operator has higher priority than the arg operator + postfixList.add(infixList.get(++i)); + postfixList.add(token); + operStack.push(topToken); + + }else{ + postfixList.add(topToken); + operStack.push(token); + } + + } + i++; + } + //empty operStack + while(!operStack.isEmpty()){ + postfixList.add((Token)operStack.pop()); + } + for (Token token :postfixList){ + System.out.print(token.value); + } + System.out.println(); + return postfixList; + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..27b9ee9c31 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,51 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +import java.util.List; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List postfixExpr = TokenParser.parse(expr); + + Stack calc = new Stack(); + for(Token token :postfixExpr){ + if(token.isNumber()){ + //push number into stack until operator + calc.push(token.getIntValue()); + }else { + //operator : pop two numbers to calculate and then push the result into stack + int numberA = (int)calc.pop(); + int numberB = (int)calc.pop(); + + switch (token.value){ + case "+": + calc.push(numberB + numberA ); + break; + case "-": + calc.push(numberB - numberA); + break; + case "*": + calc.push(numberB * numberA); + break; + case "/": + calc.push(numberB / numberA); + break; + + default: + throw new RuntimeException(token.value + " is not a operator !"); + } + } + } + + //the result is the only value in the stack + float result = Float.parseFloat(calc.pop() + ""); + return result; + } +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..956927e2df --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,18 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group27/513274874/data-structure/src/com/coding/basic/stack/expr/Token.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.coding.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 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/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParser.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..7ef3d1959c --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + + public static 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 static int indexOfNextOperator(int i, String expr) { + + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + + } + + private static boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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()); + } + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java index cf37bf22aa..da789aa68f 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.coderising.jvm.attr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; @@ -14,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; @@ -84,6 +86,18 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { return codeAttr; } + + 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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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(); + } + + } +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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); + } + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.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); + } + + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java index aea9048ea4..c8e65ff493 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -21,4 +21,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/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java index 466b072244..88353df2d3 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -26,4 +26,15 @@ 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); + + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java index 65475e194c..7ae71396ef 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -51,4 +51,8 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java index 9568c571d8..c85d1c8ccd 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -49,6 +49,11 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java index b9d9185ef8..e4f6d027e0 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -46,4 +46,10 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java index 936736016f..41e0fd7e7a 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -9,5 +9,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java index f1f8eb4ed4..6bfcb47273 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -22,5 +22,11 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java index 5cac9f04f7..7db88a939e 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -26,6 +26,11 @@ public String getValue() { public void setValue(String value) { this.value = value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java index 3d2c8e2554..d7716bf181 100644 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/method/Method.java @@ -3,6 +3,8 @@ import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; @@ -73,4 +75,24 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { return method; } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + + 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(); + } } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..ac8be13069 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.clz.ClassFile; +import com.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.getMajorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "/Users/guodongchow/Desktop/coding2017/"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..460c003aac --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,83 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getNameIndex()).append(":#") + .append(info.getDescriptorIndex()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } +} \ No newline at end of file diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java index bd32473909..8a522e4338 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; import com.coderising.jvm.constant.*; import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; @@ -264,6 +268,79 @@ 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); + } } From ccdb524d2d7648f8e7f6eef250be896bbe654c3b Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Mon, 24 Apr 2017 22:23:04 +0800 Subject: [PATCH 126/151] InfixToPostFix --- .../coding/basic/stack/expr/InfixExpr.java | 22 +++----- .../basic/stack/expr/InfixToPostfix.java | 50 +++++++++++-------- .../basic/stack/expr/InfixToPostfixTest.java | 41 +++++++++++++++ 3 files changed, 78 insertions(+), 35 deletions(-) create mode 100644 liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfixTest.java diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java index 08918c490c..cebef21fa3 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java @@ -25,22 +25,16 @@ public float evaluate() { if (token.isOperator()){ - if(opStack.isEmpty()){ + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); - opStack.push(token); - } else{ - - while(!opStack.isEmpty() - && !token.hasHigherPriority(opStack.peek())){ - Token prevOperator = opStack.pop(); - Float f2 = numStack.pop(); - Float f1 = numStack.pop(); - Float result = calculate(prevOperator.toString(), f1,f2); - numStack.push(result); - - } - opStack.push(token); } + opStack.push(token); } if(token.isNumber()){ numStack.push(new Float(token.getIntValue())); diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java index d52ec73bd3..2288e3bd29 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -1,35 +1,43 @@ package com.coding.basic.stack.expr; +import java.util.ArrayList; import java.util.List; import java.util.Stack; public class InfixToPostfix { public static List convert(String expr) { - return null; - } - - public static void main(String[] args) { - Stack stack = new Stack(); - String expr = "1+((2+3)*4)-5"; - for(int i=0;i inFixTokens = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList<>(); + + Stack opStack = new Stack(); + for(Token token : inFixTokens){ + + if(token.isOperator()){ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + postFixTokens.add(opStack.pop()); + + } + opStack.push(token); + } - else if(c == ')'){ - System.out.print(stack.pop() + " "); - } - else if(c == '('){ - System.out.print(" "); - } else{ - System.out.print(c +" "); + if(token.isNumber()){ + + postFixTokens.add(token); + } } - System.out.println(""); + + while(!opStack.isEmpty()){ + postFixTokens.add(opStack.pop()); + } + + return postFixTokens; } + + } diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfixTest.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..f879f55f14 --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,41 @@ +package com.coding.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 InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} From 90001263d0634aa37a7b399bde094b57741b2e86 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Tue, 25 Apr 2017 09:06:21 +0800 Subject: [PATCH 127/151] eighthweek homework --- .../8-EighthWeek/attr/AttributeInfo.java | 19 + .../Homework/8-EighthWeek/attr/CodeAttr.java | 70 ++++ .../8-EighthWeek/attr/LineNumberTable.java | 55 +++ .../8-EighthWeek/attr/LocalVariableItem.java | 39 ++ .../8-EighthWeek/attr/LocalVariableTable.java | 42 +++ .../8-EighthWeek/attr/StackMapTable.java | 30 ++ .../Homework/8-EighthWeek/clz/AccessFlag.java | 25 ++ .../Homework/8-EighthWeek/clz/ClassFile.java | 102 +++++ .../Homework/8-EighthWeek/clz/ClassIndex.java | 19 + .../Homework/8-EighthWeek/cmd/BiPushCmd.java | 31 ++ .../8-EighthWeek/cmd/ByteCodeCommand.java | 130 +++++++ .../8-EighthWeek/cmd/CommandParser.java | 85 +++++ .../8-EighthWeek/cmd/GetFieldCmd.java | 30 ++ .../8-EighthWeek/cmd/GetStaticFieldCmd.java | 31 ++ .../8-EighthWeek/cmd/InvokeSpecialCmd.java | 31 ++ .../8-EighthWeek/cmd/InvokeVirtualCmd.java | 29 ++ group24/Homework/8-EighthWeek/cmd/LdcCmd.java | 37 ++ .../8-EighthWeek/cmd/NewObjectCmd.java | 27 ++ .../8-EighthWeek/cmd/NoOperandCmd.java | 31 ++ .../8-EighthWeek/cmd/OneOperandCmd.java | 27 ++ .../8-EighthWeek/cmd/PutFieldCmd.java | 27 ++ .../8-EighthWeek/cmd/TwoOperandCmd.java | 67 ++++ .../8-EighthWeek/constant/ClassInfo.java | 28 ++ .../8-EighthWeek/constant/ConstantInfo.java | 40 ++ .../8-EighthWeek/constant/ConstantPool.java | 31 ++ .../8-EighthWeek/constant/FieldRefInfo.java | 58 +++ .../8-EighthWeek/constant/MethodRefInfo.java | 60 +++ .../constant/NameAndTypeInfo.java | 51 +++ .../constant/NullConstantInfo.java | 17 + .../8-EighthWeek/constant/StringInfo.java | 32 ++ .../8-EighthWeek/constant/UTF8Info.java | 37 ++ .../8-EighthWeek/engine/ExecutionResult.java | 56 +++ .../8-EighthWeek/engine/ExecutorEngine.java | 35 ++ .../Homework/8-EighthWeek/engine/Heap.java | 39 ++ .../8-EighthWeek/engine/JavaObject.java | 71 ++++ .../8-EighthWeek/engine/MethodArea.java | 68 ++++ .../Homework/8-EighthWeek/engine/MiniJVM.java | 28 ++ .../8-EighthWeek/engine/StackFrame.java | 95 +++++ .../Homework/8-EighthWeek/field/Field.java | 50 +++ .../8-EighthWeek/loader/ByteCodeIterator.java | 57 +++ .../8-EighthWeek/loader/ClassFileLoader.java | 140 +++++++ .../8-EighthWeek/loader/ClassFileParser.java | 62 +++ .../Homework/8-EighthWeek/method/Method.java | 80 ++++ .../8-EighthWeek/print/ClassFilePrinter.java | 54 +++ .../print/ConstantPoolPrinter.java | 25 ++ .../test/ClassFileloaderTest.java | 354 ++++++++++++++++++ .../8-EighthWeek/test/EmployeeV1.java | 28 ++ group24/Homework/8-EighthWeek/util/Util.java | 24 ++ 48 files changed, 2604 insertions(+) create mode 100644 group24/Homework/8-EighthWeek/attr/AttributeInfo.java create mode 100644 group24/Homework/8-EighthWeek/attr/CodeAttr.java create mode 100644 group24/Homework/8-EighthWeek/attr/LineNumberTable.java create mode 100644 group24/Homework/8-EighthWeek/attr/LocalVariableItem.java create mode 100644 group24/Homework/8-EighthWeek/attr/LocalVariableTable.java create mode 100644 group24/Homework/8-EighthWeek/attr/StackMapTable.java create mode 100644 group24/Homework/8-EighthWeek/clz/AccessFlag.java create mode 100644 group24/Homework/8-EighthWeek/clz/ClassFile.java create mode 100644 group24/Homework/8-EighthWeek/clz/ClassIndex.java create mode 100644 group24/Homework/8-EighthWeek/cmd/BiPushCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/ByteCodeCommand.java create mode 100644 group24/Homework/8-EighthWeek/cmd/CommandParser.java create mode 100644 group24/Homework/8-EighthWeek/cmd/GetFieldCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/GetStaticFieldCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/InvokeSpecialCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/InvokeVirtualCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/LdcCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/NewObjectCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/NoOperandCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/OneOperandCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/PutFieldCmd.java create mode 100644 group24/Homework/8-EighthWeek/cmd/TwoOperandCmd.java create mode 100644 group24/Homework/8-EighthWeek/constant/ClassInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/ConstantInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/ConstantPool.java create mode 100644 group24/Homework/8-EighthWeek/constant/FieldRefInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/MethodRefInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/NameAndTypeInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/NullConstantInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/StringInfo.java create mode 100644 group24/Homework/8-EighthWeek/constant/UTF8Info.java create mode 100644 group24/Homework/8-EighthWeek/engine/ExecutionResult.java create mode 100644 group24/Homework/8-EighthWeek/engine/ExecutorEngine.java create mode 100644 group24/Homework/8-EighthWeek/engine/Heap.java create mode 100644 group24/Homework/8-EighthWeek/engine/JavaObject.java create mode 100644 group24/Homework/8-EighthWeek/engine/MethodArea.java create mode 100644 group24/Homework/8-EighthWeek/engine/MiniJVM.java create mode 100644 group24/Homework/8-EighthWeek/engine/StackFrame.java create mode 100644 group24/Homework/8-EighthWeek/field/Field.java create mode 100644 group24/Homework/8-EighthWeek/loader/ByteCodeIterator.java create mode 100644 group24/Homework/8-EighthWeek/loader/ClassFileLoader.java create mode 100644 group24/Homework/8-EighthWeek/loader/ClassFileParser.java create mode 100644 group24/Homework/8-EighthWeek/method/Method.java create mode 100644 group24/Homework/8-EighthWeek/print/ClassFilePrinter.java create mode 100644 group24/Homework/8-EighthWeek/print/ConstantPoolPrinter.java create mode 100644 group24/Homework/8-EighthWeek/test/ClassFileloaderTest.java create mode 100644 group24/Homework/8-EighthWeek/test/EmployeeV1.java create mode 100644 group24/Homework/8-EighthWeek/util/Util.java diff --git a/group24/Homework/8-EighthWeek/attr/AttributeInfo.java b/group24/Homework/8-EighthWeek/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group24/Homework/8-EighthWeek/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group24/Homework/8-EighthWeek/attr/CodeAttr.java b/group24/Homework/8-EighthWeek/attr/CodeAttr.java new file mode 100644 index 0000000000..c4c0c4c6c5 --- /dev/null +++ b/group24/Homework/8-EighthWeek/attr/CodeAttr.java @@ -0,0 +1,70 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.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){ + + return null; + } + + + 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){ + + return null; + } + + 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/group24/Homework/8-EighthWeek/attr/LocalVariableItem.java b/group24/Homework/8-EighthWeek/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group24/Homework/8-EighthWeek/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.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/group24/Homework/8-EighthWeek/attr/LocalVariableTable.java b/group24/Homework/8-EighthWeek/attr/LocalVariableTable.java new file mode 100644 index 0000000000..14db5dca46 --- /dev/null +++ b/group24/Homework/8-EighthWeek/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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){ + + return null; + } + + + 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/group24/Homework/8-EighthWeek/attr/StackMapTable.java b/group24/Homework/8-EighthWeek/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group24/Homework/8-EighthWeek/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.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/group24/Homework/8-EighthWeek/clz/AccessFlag.java b/group24/Homework/8-EighthWeek/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group24/Homework/8-EighthWeek/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group24/Homework/8-EighthWeek/clz/ClassFile.java b/group24/Homework/8-EighthWeek/clz/ClassFile.java new file mode 100644 index 0000000000..2a8dfb6123 --- /dev/null +++ b/group24/Homework/8-EighthWeek/clz/ClassFile.java @@ -0,0 +1,102 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList(); + private List methods = new ArrayList(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + 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 print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + public String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + public String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group24/Homework/8-EighthWeek/clz/ClassIndex.java b/group24/Homework/8-EighthWeek/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group24/Homework/8-EighthWeek/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group24/Homework/8-EighthWeek/cmd/BiPushCmd.java b/group24/Homework/8-EighthWeek/cmd/BiPushCmd.java new file mode 100644 index 0000000000..1f60641d2d --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/BiPushCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +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(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/ByteCodeCommand.java b/group24/Homework/8-EighthWeek/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..e48d4e38f7 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/ByteCodeCommand.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +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,ExecutionResult result); +} diff --git a/group24/Homework/8-EighthWeek/cmd/CommandParser.java b/group24/Homework/8-EighthWeek/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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(); + } + + } +} diff --git a/group24/Homework/8-EighthWeek/cmd/GetFieldCmd.java b/group24/Homework/8-EighthWeek/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..c771d535f7 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/GetFieldCmd.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/GetStaticFieldCmd.java b/group24/Homework/8-EighthWeek/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6876c36bb --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/GetStaticFieldCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group24/Homework/8-EighthWeek/cmd/InvokeSpecialCmd.java b/group24/Homework/8-EighthWeek/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..8d60e72341 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/InvokeSpecialCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/InvokeVirtualCmd.java b/group24/Homework/8-EighthWeek/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..a1f2d1a1c6 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/InvokeVirtualCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + + + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/LdcCmd.java b/group24/Homework/8-EighthWeek/cmd/LdcCmd.java new file mode 100644 index 0000000000..1669aa3900 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/LdcCmd.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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; + + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group24/Homework/8-EighthWeek/cmd/NewObjectCmd.java b/group24/Homework/8-EighthWeek/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..caa2609928 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/NewObjectCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/NoOperandCmd.java b/group24/Homework/8-EighthWeek/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..c3cda9b52e --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/NoOperandCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group24/Homework/8-EighthWeek/cmd/OneOperandCmd.java b/group24/Homework/8-EighthWeek/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group24/Homework/8-EighthWeek/cmd/PutFieldCmd.java b/group24/Homework/8-EighthWeek/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..dc31cf084d --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/PutFieldCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + +} diff --git a/group24/Homework/8-EighthWeek/cmd/TwoOperandCmd.java b/group24/Homework/8-EighthWeek/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group24/Homework/8-EighthWeek/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.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/group24/Homework/8-EighthWeek/constant/ClassInfo.java b/group24/Homework/8-EighthWeek/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } +} diff --git a/group24/Homework/8-EighthWeek/constant/ConstantInfo.java b/group24/Homework/8-EighthWeek/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + 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); + + } +} diff --git a/group24/Homework/8-EighthWeek/constant/ConstantPool.java b/group24/Homework/8-EighthWeek/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } + + +} diff --git a/group24/Homework/8-EighthWeek/constant/FieldRefInfo.java b/group24/Homework/8-EighthWeek/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } +} diff --git a/group24/Homework/8-EighthWeek/constant/MethodRefInfo.java b/group24/Homework/8-EighthWeek/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group24/Homework/8-EighthWeek/constant/NameAndTypeInfo.java b/group24/Homework/8-EighthWeek/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group24/Homework/8-EighthWeek/constant/NullConstantInfo.java b/group24/Homework/8-EighthWeek/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group24/Homework/8-EighthWeek/constant/StringInfo.java b/group24/Homework/8-EighthWeek/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + +} diff --git a/group24/Homework/8-EighthWeek/constant/UTF8Info.java b/group24/Homework/8-EighthWeek/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/group24/Homework/8-EighthWeek/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } + + + +} diff --git a/group24/Homework/8-EighthWeek/engine/ExecutionResult.java b/group24/Homework/8-EighthWeek/engine/ExecutionResult.java new file mode 100644 index 0000000000..8f6c51e52a --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group24/Homework/8-EighthWeek/engine/ExecutorEngine.java b/group24/Homework/8-EighthWeek/engine/ExecutorEngine.java new file mode 100644 index 0000000000..5d6b582879 --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/ExecutorEngine.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + + } + +} diff --git a/group24/Homework/8-EighthWeek/engine/Heap.java b/group24/Homework/8-EighthWeek/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/Homework/8-EighthWeek/engine/JavaObject.java b/group24/Homework/8-EighthWeek/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/Homework/8-EighthWeek/engine/MethodArea.java b/group24/Homework/8-EighthWeek/engine/MethodArea.java new file mode 100644 index 0000000000..781e81acf1 --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/MethodArea.java @@ -0,0 +1,68 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/group24/Homework/8-EighthWeek/engine/MiniJVM.java b/group24/Homework/8-EighthWeek/engine/MiniJVM.java new file mode 100644 index 0000000000..443524cc5f --- /dev/null +++ b/group24/Homework/8-EighthWeek/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group24/Homework/8-EighthWeek/field/Field.java b/group24/Homework/8-EighthWeek/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/group24/Homework/8-EighthWeek/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.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/group24/Homework/8-EighthWeek/loader/ByteCodeIterator.java b/group24/Homework/8-EighthWeek/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/group24/Homework/8-EighthWeek/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group24/Homework/8-EighthWeek/loader/ClassFileLoader.java b/group24/Homework/8-EighthWeek/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group24/Homework/8-EighthWeek/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + 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); + } + + @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/group24/Homework/8-EighthWeek/test/EmployeeV1.java b/group24/Homework/8-EighthWeek/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group24/Homework/8-EighthWeek/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group24/Homework/8-EighthWeek/util/Util.java b/group24/Homework/8-EighthWeek/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group24/Homework/8-EighthWeek/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i Date: Tue, 25 Apr 2017 11:10:43 +0800 Subject: [PATCH 128/151] =?UTF-8?q?20170424=5F1110=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding2017/basic/queue/CircleQueue.java | 50 +++++++++++++++++++ .../coding2017/basic/queue/Josephus.java | 40 +++++++++++++++ .../basic/queue/QueueWithTwoStacks.java | 42 ++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/basic/queue/CircleQueue.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/basic/queue/Josephus.java create mode 100644 group02/562768642/src/com/github/orajavac/coding2017/basic/queue/QueueWithTwoStacks.java diff --git a/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/CircleQueue.java b/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..b26e98cd5d --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/CircleQueue.java @@ -0,0 +1,50 @@ +package com.github.orajavac.coding2017.basic.queue; + +public class CircleQueue { +private final static int DEFAULT_SIZE = 8; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + if (front==0&&rear==0){ + return true; + } + return false; + + } + + public int size() { + return DEFAULT_SIZE; + } + + + + public void enQueue(E data) { + if (rear==DEFAULT_SIZE&&elementData[0]==null){ + rear = 0; + elementData[rear]=data; + }else if (elementData[rear]==null){ + elementData[rear]=data; + }else{ + throw new RuntimeException("队列已满"); + } + rear++; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + Object o = elementData[front]; + elementData[front] = null; + front++; + if (front == DEFAULT_SIZE){ + front = 0; + } + return (E)o; + } +} diff --git a/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/Josephus.java b/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..05e692a8aa --- /dev/null +++ b/group02/562768642/src/com/github/orajavac/coding2017/basic/queue/Josephus.java @@ -0,0 +1,40 @@ +package com.github.orajavac.coding2017.basic.queue; + +import java.util.ArrayList; +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){ + CircleQueue q = new CircleQueue(); + List l = new ArrayList(); + for (int i=1;i<=n;i++){ + q.enQueue(i); + } + for (int i=0;i l = execute(8,4); + for (int i=0;i { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.size()==0; + } + + + + public int size() { + return stack1.size(); + } + + + + public void enQueue(E item) { + int len1 = stack1.size(); + for (int i=0;i Date: Tue, 25 Apr 2017 18:46:39 +0800 Subject: [PATCH 129/151] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group17/785396327/4.23/queue/CircleQueue.java | 35 +++++++++-- .../785396327/4.23/queue/CircleQueueTest.java | 62 +++++++++++++++++++ group17/785396327/4.23/queue/Josephus.java | 26 +++++++- .../785396327/4.23/queue/JosephusTest.java | 2 +- 4 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 group17/785396327/4.23/queue/CircleQueueTest.java diff --git a/group17/785396327/4.23/queue/CircleQueue.java b/group17/785396327/4.23/queue/CircleQueue.java index 228bf1aba1..a7ab62bf55 100644 --- a/group17/785396327/4.23/queue/CircleQueue.java +++ b/group17/785396327/4.23/queue/CircleQueue.java @@ -1,5 +1,7 @@ package queue; +import java.util.Arrays; + /** * Created by gongxun on 2017/4/24. * 用数组实现循环队列 @@ -8,7 +10,7 @@ public class CircleQueue { private final static int DEFAULT_SIZE = 10; //用数组来保存循环队列的元素 - private Object[] elementData = new Object[DEFAULT_SIZE] ; + private Object[] elementData = new Object[DEFAULT_SIZE]; //队头 private int front = 0; @@ -16,21 +18,42 @@ public class CircleQueue { private int rear = 0; public boolean isEmpty() { - return false; + return front == rear && elementData[front] == null; } public int size() { - return -1; + if (isEmpty()) + return 0; + return front - rear > 0 ? DEFAULT_SIZE - front + rear : front - rear < 0 ? rear - front : DEFAULT_SIZE; } - public void enQueue(E data) { - + if (size() != DEFAULT_SIZE) { + elementData[rear] = data; + if (rear == DEFAULT_SIZE - 1) + rear = 0; + else + rear++; + } } public E deQueue() { - return null; + E removeEle = null; + if (!isEmpty()) { + removeEle = (E) elementData[front]; + elementData[front] = null; + if (front == DEFAULT_SIZE - 1) + front = 0; + else + front++; + } + return removeEle; + } + + @Override + public String toString() { + return Arrays.toString(elementData); } } diff --git a/group17/785396327/4.23/queue/CircleQueueTest.java b/group17/785396327/4.23/queue/CircleQueueTest.java new file mode 100644 index 0000000000..1a3f97d9bf --- /dev/null +++ b/group17/785396327/4.23/queue/CircleQueueTest.java @@ -0,0 +1,62 @@ +package queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/25. + */ +public class CircleQueueTest { + @Before + public void startUp() { + + } + + @After + public void tearDown() { + + } + + @Test + public void testEnQueue() { + CircleQueue circleQueue = new CircleQueue(); + { + for (int i = 0; i < 9; i++) { + circleQueue.enQueue(i); + } + } + + { + + Assert.assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, null]", circleQueue.toString()); + Assert.assertEquals(9, circleQueue.size()); + + circleQueue.enQueue(9); + Assert.assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", circleQueue.toString()); + Assert.assertEquals(10, circleQueue.size()); + + circleQueue.enQueue(10); + Assert.assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", circleQueue.toString()); + Assert.assertEquals(10, circleQueue.size()); + } + + { + int removeEle = circleQueue.deQueue(); + Assert.assertEquals(0, removeEle); + circleQueue.deQueue(); + circleQueue.deQueue(); + circleQueue.deQueue(); + Assert.assertEquals("[null, null, null, null, 4, 5, 6, 7, 8, 9]", circleQueue.toString()); + } + { + circleQueue.enQueue(-1); + Assert.assertEquals("[-1, null, null, null, 4, 5, 6, 7, 8, 9]", circleQueue.toString()); + Assert.assertEquals(7, circleQueue.size()); + } + + } + + +} diff --git a/group17/785396327/4.23/queue/Josephus.java b/group17/785396327/4.23/queue/Josephus.java index 7d85d94a01..7285c64dfe 100644 --- a/group17/785396327/4.23/queue/Josephus.java +++ b/group17/785396327/4.23/queue/Josephus.java @@ -1,5 +1,6 @@ package queue; +import java.util.ArrayList; import java.util.List; /** @@ -10,6 +11,29 @@ */ public class Josephus { public static List execute(int n, int m) { - return null; + if (m <= 0) + return null; + List origin = new ArrayList(); + List sequence = new ArrayList(); + for (int i = 0; i < n; i++) { + origin.add(i); + } + int count = 1;//计数器 + int index = count - 1;//当前元素的索引 + while (origin.size() > 1) { + if (count == m) { + sequence.add(origin.remove(index)); + count = 1;//删除一个元素,则重新计数 + } else { + count++; + if (index == origin.size() - 1) + //遍历到最后一个元素,重回头索引 + index = 0; + else + index++; + } + } + sequence.add(origin.get(0)); + return sequence; } } diff --git a/group17/785396327/4.23/queue/JosephusTest.java b/group17/785396327/4.23/queue/JosephusTest.java index ba502d0ffb..87fe65211d 100644 --- a/group17/785396327/4.23/queue/JosephusTest.java +++ b/group17/785396327/4.23/queue/JosephusTest.java @@ -21,6 +21,6 @@ public void tearDown() throws Exception { public void testExecute() { Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); - + Assert.assertEquals("[1, 0, 2]", Josephus.execute(3, 2).toString()); } } From 0e272c9e8389a3989baf32e9139500da51f25190 Mon Sep 17 00:00:00 2001 From: DonaldY <448641125@qq.com> Date: Tue, 25 Apr 2017 21:13:30 +0800 Subject: [PATCH 130/151] update --- .../src/com/donaldy/jvm/cmd/BiPushCmd.java | 10 +- .../com/donaldy/jvm/cmd/ByteCodeCommand.java | 6 +- .../src/com/donaldy/jvm/cmd/GetFieldCmd.java | 8 +- .../donaldy/jvm/cmd/GetStaticFieldCmd.java | 8 ++ .../com/donaldy/jvm/cmd/InvokeSpecialCmd.java | 8 +- .../com/donaldy/jvm/cmd/InvokeVirtualCmd.java | 7 +- .../src/com/donaldy/jvm/cmd/LdcCmd.java | 8 ++ .../src/com/donaldy/jvm/cmd/NewObjectCmd.java | 7 ++ .../src/com/donaldy/jvm/cmd/NoOperandCmd.java | 9 ++ .../src/com/donaldy/jvm/cmd/PutFieldCmd.java | 8 ++ .../donaldy/jvm/engine/ExecutionResult.java | 56 +++++++++++ .../donaldy/jvm/engine/ExecutorEngine.java | 35 +++++++ .../src/com/donaldy/jvm/engine/Heap.java | 39 ++++++++ .../com/donaldy/jvm/engine/JavaObject.java | 71 ++++++++++++++ .../com/donaldy/jvm/engine/MethodArea.java | 68 +++++++++++++ .../src/com/donaldy/jvm/engine/MiniJVM.java | 28 ++++++ .../com/donaldy/jvm/engine/StackFrame.java | 95 +++++++++++++++++++ 17 files changed, 464 insertions(+), 7 deletions(-) create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/Heap.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/JavaObject.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java create mode 100644 group24/448641125/src/com/donaldy/jvm/engine/StackFrame.java diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java index 266edbc5e8..4126097c3f 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/BiPushCmd.java @@ -3,6 +3,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantInfo; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -17,7 +19,11 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } - - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java b/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java index 48ded9618a..a611d4273b 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/ByteCodeCommand.java @@ -6,6 +6,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantInfo; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public abstract class ByteCodeCommand { @@ -123,6 +125,6 @@ public String getReadableCodeText(){ } return txt; } - - //public abstract void execute(StackFrame frame,FrameResult result); + + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java index 9fe5244f8a..6644fe958d 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -16,7 +18,11 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java index 21236d26c6..7b4cc9896f 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java @@ -5,6 +5,8 @@ import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.FieldRefInfo; import com.donaldy.jvm.constant.UTF8Info; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -20,4 +22,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java index 7b56e9009b..b646011143 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java @@ -3,6 +3,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.MethodRefInfo; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -18,6 +20,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java index 58e1d1ff5e..8b51e481af 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java @@ -2,6 +2,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -16,7 +18,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java index 28fe64a88d..d55d8ef409 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java @@ -4,6 +4,8 @@ import com.donaldy.jvm.constant.ConstantInfo; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.StringInfo; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -25,5 +27,11 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java index 27c8cd13ca..2a30581935 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java @@ -2,6 +2,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -15,5 +17,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java index 40d11a7bce..c664210eda 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java @@ -2,6 +2,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -20,4 +22,11 @@ public int getLength(){ return 1; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java index 4b3b8c1fab..9bf85ba44f 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java @@ -2,6 +2,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -16,4 +18,10 @@ public String toString(ConstantPool pool) { } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + } diff --git a/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java b/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..c90cc8fc65 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.donaldy.jvm.engine; + +import com.donaldy.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java b/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..1fb57626b9 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java @@ -0,0 +1,35 @@ +package com.donaldy.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.donaldy.jvm.attr.CodeAttr; +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.cmd.ByteCodeCommand; +import com.donaldy.jvm.constant.MethodRefInfo; +import com.donaldy.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/engine/Heap.java b/group24/448641125/src/com/donaldy/jvm/engine/Heap.java new file mode 100644 index 0000000000..250d70504d --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.donaldy.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/engine/JavaObject.java b/group24/448641125/src/com/donaldy/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..d5c5884af2 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.donaldy.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java b/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..fea5102cd0 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java @@ -0,0 +1,68 @@ +package com.donaldy.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.MethodRefInfo; +import com.donaldy.jvm.loader.ClassFileLoader; +import com.donaldy.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java b/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..30f19e0d8c --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.donaldy.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.donaldy.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} From 05a8b2d32ec268d5c063300f4905ef22e54444a6 Mon Sep 17 00:00:00 2001 From: guodongym Date: Tue, 25 Apr 2017 22:33:46 +0800 Subject: [PATCH 131/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/zhaogd/array/ArrayList.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/group12/377401843/learning/src/main/java/com/zhaogd/array/ArrayList.java b/group12/377401843/learning/src/main/java/com/zhaogd/array/ArrayList.java index d5c5fe04cc..f5cd3f3857 100644 --- a/group12/377401843/learning/src/main/java/com/zhaogd/array/ArrayList.java +++ b/group12/377401843/learning/src/main/java/com/zhaogd/array/ArrayList.java @@ -1,10 +1,10 @@ package com.zhaogd.array; -import java.util.Arrays; - import com.zhaogd.collection.Iterator; import com.zhaogd.collection.List; +import java.util.Arrays; + public class ArrayList implements List { private int size = 0; @@ -16,7 +16,6 @@ public class ArrayList implements List { * * @Method add * @param o - * @see com.zhaogd.collection.guodong.datastructure.List#add(java.lang.Object) */ public void add(Object o) { ensureCapacityInternal(size + 1); @@ -30,7 +29,6 @@ public void add(Object o) { * @Method add * @param index * @param o - * @see com.zhaogd.collection.guodong.datastructure.List#add(int, java.lang.Object) */ public void add(int index, Object o) { checkRangeForAdd(index); @@ -49,7 +47,6 @@ public void add(int index, Object o) { * @Method get * @param index * @return - * @see com.zhaogd.collection.guodong.datastructure.List#get(int) */ public Object get(int index) { checkRangeForGetOrRemove(index); @@ -63,7 +60,6 @@ public Object get(int index) { * @Method remove * @param index * @return - * @see com.zhaogd.collection.guodong.datastructure.List#remove(int) */ public Object remove(int index) { checkRangeForGetOrRemove(index); @@ -83,7 +79,6 @@ public Object remove(int index) { * * @Method size * @return - * @see com.zhaogd.collection.guodong.datastructure.List#size() */ public int size() { return size; From 02c15e8973b9c0165ac80565975302e55552deba Mon Sep 17 00:00:00 2001 From: maishihang <446031103@qq.com> Date: Tue, 25 Apr 2017 23:12:35 +0800 Subject: [PATCH 132/151] update jvm the third work --- .../datastructure/stack/expr/InfixExpr.java | 67 +++++++++++++++++++ .../stack/expr/InfixExprTest.java | 51 ++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 group12/446031103/src/com/datastructure/stack/expr/InfixExpr.java create mode 100644 group12/446031103/src/com/datastructure/stack/expr/InfixExprTest.java diff --git a/group12/446031103/src/com/datastructure/stack/expr/InfixExpr.java b/group12/446031103/src/com/datastructure/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..503f050d29 --- /dev/null +++ b/group12/446031103/src/com/datastructure/stack/expr/InfixExpr.java @@ -0,0 +1,67 @@ +package com.datastructure.stack.expr; + +import java.util.Objects; +import java.util.Stack; +import java.lang.String; +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + Stack sign = new Stack(); + Stack number = new Stack(); + int strCnt = 0; + int numberLen = 0; + String[] String = expr.split("[^\\d]"); + if(expr!=null){ + for (int i = 0,strLen = expr.length(); i < strLen; i++) { + char c=expr.charAt(i); + if(Objects.equals(c, '+')||Objects.equals(c, '-')){ + sign.push(c); + }else if(Objects.equals(c, '*')||Objects.equals(c, '/')){ + float number1=number.pop(); + float number2=Float.parseFloat(String[strCnt]); + float result=calculate(number1,number2,c); + numberLen = String[strCnt].length(); + number.push(result); + i += numberLen; + strCnt++; + }else{ + number.push(Float.parseFloat(String[strCnt])); + numberLen = String[strCnt].length(); + strCnt++; + i += (numberLen-1); + } + } + for (int i = 0,signS = sign.size(); i < signS; i++) { + float number1 = number.pop(); + float number2 =number.pop(); + char c = sign.pop(); + float result=calculate(number2,number1,c); + number.push(result); + } + } + return number.pop(); + } + + private float calculate(float number1,float number2,char c){ + float result = 0; + if(Objects.equals(c, '+')){ + result = number1 + number2; + }else if(Objects.equals(c, '-')){ + result = number1 - number2; + }else if(Objects.equals(c, '*')){ + result = number1 * number2; + }else if(Objects.equals(c, '/')){ + result = number1 / number2; + } + return result; + } + + + + +} diff --git a/group12/446031103/src/com/datastructure/stack/expr/InfixExprTest.java b/group12/446031103/src/com/datastructure/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..1b64b3fcc7 --- /dev/null +++ b/group12/446031103/src/com/datastructure/stack/expr/InfixExprTest.java @@ -0,0 +1,51 @@ +package com.datastructure.stack.expr; + + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + float a =expr.evaluate(); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} From 417d7ca6e60ac7c2934fbb1eacf8f85d730f66e4 Mon Sep 17 00:00:00 2001 From: gongxun Date: Wed, 26 Apr 2017 18:37:36 +0800 Subject: [PATCH 133/151] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../4.23/queue/QueueWithTwoStacks.java | 30 ++++++++++----- .../4.23/queue/QueueWithTwoStacksTest.java | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 group17/785396327/4.23/queue/QueueWithTwoStacksTest.java diff --git a/group17/785396327/4.23/queue/QueueWithTwoStacks.java b/group17/785396327/4.23/queue/QueueWithTwoStacks.java index 7f38a9c20c..995bab9904 100644 --- a/group17/785396327/4.23/queue/QueueWithTwoStacks.java +++ b/group17/785396327/4.23/queue/QueueWithTwoStacks.java @@ -16,27 +16,39 @@ public QueueWithTwoStacks() { } - - public boolean isEmpty() { - return false; + return stack1.size() == 0; } - public int size() { - return -1; + return stack1.size(); } - public void enQueue(E item) { - + Stack temp = new Stack(); + stack1.push(item); + while (!stack2.isEmpty()) + temp.push(stack2.pop()); + temp.push(item); + while (!temp.isEmpty()) + stack2.push(temp.pop()); } public E deQueue() { - return null; + Stack temp = new Stack(); + E ele = stack2.pop(); + while (!stack1.isEmpty()) + temp.push(stack1.pop()); + temp.pop(); + while (!temp.isEmpty()) + stack1.push(temp.pop()); + return ele; } - + @Override + public String toString() { + return stack1.toString() + "\n" + stack2.toString(); + } } diff --git a/group17/785396327/4.23/queue/QueueWithTwoStacksTest.java b/group17/785396327/4.23/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..e0c90c4b66 --- /dev/null +++ b/group17/785396327/4.23/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,37 @@ +package queue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by gongxun on 2017/4/26. + */ +public class QueueWithTwoStacksTest { + + private QueueWithTwoStacks queue; + + @Before + public void startUp() { + queue = new QueueWithTwoStacks(); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + } + + @After + public void tearDown() { + + } + + @Test + public void enQueueTest() { + System.out.println(queue); + } + + @Test + public void deQueueTest() { + queue.deQueue(); + System.out.println(queue); + } +} From f27dcfa242be608a215002031c330f70e1e5ea9c Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Wed, 26 Apr 2017 19:04:35 +0800 Subject: [PATCH 134/151] add home work count --- group17/article/20170416-20170423.md | 56 ++++++++++++++++++++++++++++ group17/count/homework.md | 2 + 2 files changed, 58 insertions(+) create mode 100644 group17/article/20170416-20170423.md diff --git a/group17/article/20170416-20170423.md b/group17/article/20170416-20170423.md new file mode 100644 index 0000000000..3d45ad0516 --- /dev/null +++ b/group17/article/20170416-20170423.md @@ -0,0 +1,56 @@ +# 自由写作 + +## 须知 +--- + +交作业时请在QQ 号后面填上各自的文章链接, 比如: + +51075907 http://m.blog.csdn.net/article/details?id=57083764 + +## 文章 +--- + +1204187480 + +102228177 + +876385982 + +785396327 + +1059107701 + +240094626 + +82427129 + +296910598 + +1264835468 + +516886559 + +1282579502 + +614982500 + +865797761 + +1540186032 + +176653813 + +116665530 + +51075907 + +1158154002 + +345450234 + +919764878 + +1368331120 + +517970312 + diff --git a/group17/count/homework.md b/group17/count/homework.md index 9422c2f12c..23e71c2fbe 100644 --- a/group17/count/homework.md +++ b/group17/count/homework.md @@ -22,3 +22,5 @@ * [20170402-20170409](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170402-20170409.md) * [20170409-20170416](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170409-20170416.md) + + * [20170416-20170423](https://github.com/luoziyihao/coding2017/blob/master/group17/article/20170416-20170423.md) From 9d5690bc7114821e84a2665d42adcda3d6035968 Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Wed, 26 Apr 2017 23:41:59 +0800 Subject: [PATCH 135/151] com --- group17/1204187480/note/todo/homework.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 group17/1204187480/note/todo/homework.md diff --git a/group17/1204187480/note/todo/homework.md b/group17/1204187480/note/todo/homework.md new file mode 100644 index 0000000000..5f111a9ea6 --- /dev/null +++ b/group17/1204187480/note/todo/homework.md @@ -0,0 +1,8 @@ +# 0326 操作系统中的lru算法 + +ClassFileLoader + +LRUPageFrame + +深入理解java虚拟机 第6章 + From 951410b9a19188c2334eed7b76e93b3e9900ff46 Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Thu, 27 Apr 2017 00:28:29 +0800 Subject: [PATCH 136/151] refactor --- .../1204187480/code/homework/basic/pom.xml | 12 - .../litestruts/{action => }/LoginAction.java | 2 +- .../coderising/src/main/resources/struts.xml | 2 +- .../main/java/com/coding/basic/ArrayList.java | 216 +++++++++--------- .../java/com/coding/basic/BinaryTreeNode.java | 64 +++--- .../main/java/com/coding/basic/Iterator.java | 14 +- .../java/com/coding/basic/LinkedList.java | 0 .../src/main/java/com/coding/basic/List.java | 20 +- .../src/main/java/com/coding/basic/Queue.java | 48 ++-- .../src/main/java/com/coding/basic/Stack.java | 60 ++--- .../test/java/com/coding/api/ArraysTest.java | 44 ++-- .../test/java/com/coding/api/SystemTest.java | 48 ++-- .../java/com/coding/basic/ArrayListTest.java | 68 +++--- .../java/com/coding/basic/LinkedListTest.java | 23 +- group17/1204187480/code/homework/pom.xml | 2 +- 15 files changed, 310 insertions(+), 313 deletions(-) delete mode 100644 group17/1204187480/code/homework/basic/pom.xml rename group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/{action => }/LoginAction.java (95%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/ArrayList.java (96%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/BinaryTreeNode.java (94%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/Iterator.java (93%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/LinkedList.java (100%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/List.java (95%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/Queue.java (93%) rename group17/1204187480/code/homework/{basic => coding}/src/main/java/com/coding/basic/Stack.java (95%) rename group17/1204187480/code/homework/{basic => coding}/src/test/java/com/coding/api/ArraysTest.java (95%) rename group17/1204187480/code/homework/{basic => coding}/src/test/java/com/coding/api/SystemTest.java (95%) rename group17/1204187480/code/homework/{basic => coding}/src/test/java/com/coding/basic/ArrayListTest.java (94%) rename group17/1204187480/code/homework/{basic => coding}/src/test/java/com/coding/basic/LinkedListTest.java (97%) diff --git a/group17/1204187480/code/homework/basic/pom.xml b/group17/1204187480/code/homework/basic/pom.xml deleted file mode 100644 index 17b2dea49e..0000000000 --- a/group17/1204187480/code/homework/basic/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - 4.0.0 - basic - - com.coding - parent - 1.0-SNAPSHOT - ../parent/pom.xml - - - \ No newline at end of file diff --git a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/action/LoginAction.java b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/LoginAction.java similarity index 95% rename from group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/action/LoginAction.java rename to group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/LoginAction.java index 85ae4dc47c..dcdbe226ed 100644 --- a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/action/LoginAction.java +++ b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/litestruts/LoginAction.java @@ -1,4 +1,4 @@ -package com.coderising.litestruts.action; +package com.coderising.litestruts; /** * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 diff --git a/group17/1204187480/code/homework/coderising/src/main/resources/struts.xml b/group17/1204187480/code/homework/coderising/src/main/resources/struts.xml index c7ee86e436..876156eb4d 100644 --- a/group17/1204187480/code/homework/coderising/src/main/resources/struts.xml +++ b/group17/1204187480/code/homework/coderising/src/main/resources/struts.xml @@ -1,6 +1,6 @@ - + /jsp/homepage.jsp /jsp/showLogin.jsp diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/ArrayList.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java similarity index 96% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/ArrayList.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java index d09d63c2fa..6ddf8cef58 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/ArrayList.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java @@ -1,108 +1,108 @@ -package com.coding.basic; - -import java.util.Arrays; - -public class ArrayList implements List { - - private int size = 0; - - private Object[] elementData = new Object[100]; - - private Iterator iterator = new ArrayListIterator(); - - private int length() { - return elementData.length; - } - - private static final int ENLARGE_LENGTH = 100; - - private Object[] enlarge(Object[] origin) { - return Arrays.copyOf(origin, origin.length + ENLARGE_LENGTH); - } - - private void enLargeElementData() { - if (size == length()) { - elementData = enlarge(elementData); - } - } - - public void add(Object o) { - enLargeElementData(); - elementData[size] = o; - size++; - } - - public void add(int index, Object o) { - checkForAdd(index); - enLargeElementData(); - // 备份 index 处及后面的数据 - Object[] elementsBehindIndex = backBehindElements(elementData, index); - // 给index处 设值 - elementData[index] = o; - // 追加 备份的数据 - appendElement(elementData, index, elementsBehindIndex); - size++; - } - - private void appendElement(Object[] origin, int pos, Object[] append) { - System.arraycopy(append, 0, origin, pos, append.length); - } - - private Object[] backBehindElements(Object[] elementData, int index) { - int backSize = size - index; - Object[] back = new Object[backSize]; - System.arraycopy(elementData, index, back, 0, backSize); - return back; - } - - public Object get(int index) { - checkIndex(index); - return elementData[index]; - } - - private void checkIndex(int index) { - if (index < 0 || index >= size) { - throw new ArrayIndexOutOfBoundsException(String.format("index=%s, size=%s", index, size)); - } - } - - private void checkForAdd(int index) { - if (index < 0 || index > size) { - throw new ArrayIndexOutOfBoundsException(String.format("index=%s, size=%s", index, size)); - } - } - - public Object remove(int index) { - checkIndex(index); - Object[] back = backBehindElements(elementData, index + 1); - System.arraycopy(back, 0, elementData, index, back.length); - Object ret = elementData[index]; - elementData[index] = null; - size--; - return ret; - } - - public int size() { - return size; - } - - public Iterator iterator() { - return iterator; - } - - private class ArrayListIterator implements Iterator { - - int next = 0; - - @Override - public boolean hasNext() { - return next < size; - } - - @Override - public Object next() { - return elementData[next++]; - } - } - -} +package com.coding.basic; + +import java.util.Arrays; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + private Iterator iterator = new ArrayListIterator(); + + private int length() { + return elementData.length; + } + + private static final int ENLARGE_LENGTH = 100; + + private Object[] enlarge(Object[] origin) { + return Arrays.copyOf(origin, origin.length + ENLARGE_LENGTH); + } + + private void enLargeElementData() { + if (size == length()) { + elementData = enlarge(elementData); + } + } + + public void add(Object o) { + enLargeElementData(); + elementData[size] = o; + size++; + } + + public void add(int index, Object o) { + checkForAdd(index); + enLargeElementData(); + // 备份 index 处及后面的数据 + Object[] elementsBehindIndex = backBehindElements(elementData, index); + // 给index处 设值 + elementData[index] = o; + // 追加 备份的数据 + appendElement(elementData, index, elementsBehindIndex); + size++; + } + + private void appendElement(Object[] origin, int pos, Object[] append) { + System.arraycopy(append, 0, origin, pos, append.length); + } + + private Object[] backBehindElements(Object[] elementData, int index) { + int backSize = size - index; + Object[] back = new Object[backSize]; + System.arraycopy(elementData, index, back, 0, backSize); + return back; + } + + public Object get(int index) { + checkIndex(index); + return elementData[index]; + } + + private void checkIndex(int index) { + if (index < 0 || index >= size) { + throw new ArrayIndexOutOfBoundsException(String.format("index=%s, size=%s", index, size)); + } + } + + private void checkForAdd(int index) { + if (index < 0 || index > size) { + throw new ArrayIndexOutOfBoundsException(String.format("index=%s, size=%s", index, size)); + } + } + + public Object remove(int index) { + checkIndex(index); + Object[] back = backBehindElements(elementData, index + 1); + System.arraycopy(back, 0, elementData, index, back.length); + Object ret = elementData[index]; + elementData[index] = null; + size--; + return ret; + } + + public int size() { + return size; + } + + public Iterator iterator() { + return iterator; + } + + private class ArrayListIterator implements Iterator { + + int next = 0; + + @Override + public boolean hasNext() { + return next < size; + } + + @Override + public Object next() { + return elementData[next++]; + } + } + +} diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/BinaryTreeNode.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/BinaryTreeNode.java similarity index 94% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/BinaryTreeNode.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/BinaryTreeNode.java index 266eff3d56..d7ac820192 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/BinaryTreeNode.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/BinaryTreeNode.java @@ -1,32 +1,32 @@ -package com.coding.basic; - -public class BinaryTreeNode { - - private Object data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public Object getData() { - return data; - } - public void setData(Object data) { - this.data = data; - } - public BinaryTreeNode getLeft() { - return left; - } - public void setLeft(BinaryTreeNode left) { - this.left = left; - } - public BinaryTreeNode getRight() { - return right; - } - public void setRight(BinaryTreeNode right) { - this.right = right; - } - - public BinaryTreeNode insert(Object o){ - return null; - } - -} +package com.coding.basic; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Iterator.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Iterator.java similarity index 93% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Iterator.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Iterator.java index dbe8b9afb2..06ef6311b2 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Iterator.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Iterator.java @@ -1,7 +1,7 @@ -package com.coding.basic; - -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/LinkedList.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/LinkedList.java similarity index 100% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/LinkedList.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/LinkedList.java diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/List.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/List.java similarity index 95% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/List.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/List.java index 0a09990083..ef939ae2cc 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/List.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/List.java @@ -1,10 +1,10 @@ -package com.coding.basic; - -public interface List { - public void add(Object o); - public void add(int index, Object o); - public Object get(int index); - public Object remove(int index); - public int size(); - public Iterator iterator(); -} +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); + public Iterator iterator(); +} diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Queue.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java similarity index 93% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Queue.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java index 10560f969e..0f6caaec6f 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Queue.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java @@ -1,24 +1,24 @@ -package com.coding.basic; - -import java.util.Arrays; - -public class Queue { - - private LinkedList elementData = new LinkedList(); - - public void enQueue(Object o){ - elementData.add(o); - } - - public Object deQueue(){ - return elementData.remove(0); - } - - public boolean isEmpty(){ - return size() == 0; - } - - public int size(){ - return elementData.size(); - } -} +package com.coding.basic; + +import java.util.Arrays; + +public class Queue { + + private LinkedList elementData = new LinkedList(); + + public void enQueue(Object o){ + elementData.add(o); + } + + public Object deQueue(){ + return elementData.remove(0); + } + + public boolean isEmpty(){ + return size() == 0; + } + + public int size(){ + return elementData.size(); + } +} diff --git a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Stack.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java similarity index 95% rename from group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Stack.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java index 998ddf9768..7d91c326e0 100644 --- a/group17/1204187480/code/homework/basic/src/main/java/com/coding/basic/Stack.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java @@ -1,30 +1,30 @@ -package com.coding.basic; - -public class Stack { - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - elementData.add(o); - } - - public Object pop(){ - if (isEmpty()) { - throw new IllegalStateException("the stack is empty"); - } - return elementData.remove(elementData.size() - 1); - } - - public Object peek(){ - if (isEmpty()) { - throw new IllegalStateException("the stack is empty"); - } - return elementData.get(elementData.size() - 1); - } - - public boolean isEmpty(){ - return size() == 0; - } - public int size(){ - return elementData.size(); - } -} +package com.coding.basic; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + if (isEmpty()) { + throw new IllegalStateException("the stack is empty"); + } + return elementData.remove(elementData.size() - 1); + } + + public Object peek(){ + if (isEmpty()) { + throw new IllegalStateException("the stack is empty"); + } + return elementData.get(elementData.size() - 1); + } + + public boolean isEmpty(){ + return size() == 0; + } + public int size(){ + return elementData.size(); + } +} diff --git a/group17/1204187480/code/homework/basic/src/test/java/com/coding/api/ArraysTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/api/ArraysTest.java similarity index 95% rename from group17/1204187480/code/homework/basic/src/test/java/com/coding/api/ArraysTest.java rename to group17/1204187480/code/homework/coding/src/test/java/com/coding/api/ArraysTest.java index 6c96193d82..eb41a7e262 100644 --- a/group17/1204187480/code/homework/basic/src/test/java/com/coding/api/ArraysTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/api/ArraysTest.java @@ -1,22 +1,22 @@ -package com.coding.api; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; - -/** - * Created by luoziyihao on 2/25/17. - */ -public class ArraysTest { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - - @Test - public void testCopyOf(){ - Object[] a = new Object[]{1, 2, 3, 4}; - Object[] b = Arrays.copyOf(a, 10); - logger.info("a={}, b={}", Arrays.toString(a), Arrays.toString(b)); - } -} +package com.coding.api; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +/** + * Created by luoziyihao on 2/25/17. + */ +public class ArraysTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Test + public void testCopyOf(){ + Object[] a = new Object[]{1, 2, 3, 4}; + Object[] b = Arrays.copyOf(a, 10); + logger.info("a={}, b={}", Arrays.toString(a), Arrays.toString(b)); + } +} diff --git a/group17/1204187480/code/homework/basic/src/test/java/com/coding/api/SystemTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/api/SystemTest.java similarity index 95% rename from group17/1204187480/code/homework/basic/src/test/java/com/coding/api/SystemTest.java rename to group17/1204187480/code/homework/coding/src/test/java/com/coding/api/SystemTest.java index 6a23cb125e..efc4022378 100644 --- a/group17/1204187480/code/homework/basic/src/test/java/com/coding/api/SystemTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/api/SystemTest.java @@ -1,24 +1,24 @@ -package com.coding.api; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; - -/** - * Created by luoziyihao on 2/25/17. - */ -public class SystemTest { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Test - public void testArrayCopy() { - int[] a = new int[]{1, 2, 3, 4, 5, 6, 7}; - int[] b = new int[]{11, 22, 33, 44, 55, 66, 77}; - System.arraycopy(a, 2, b, 4, 3); - logger.info("b={}", Arrays.toString(b)); - - } -} +package com.coding.api; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +/** + * Created by luoziyihao on 2/25/17. + */ +public class SystemTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void testArrayCopy() { + int[] a = new int[]{1, 2, 3, 4, 5, 6, 7}; + int[] b = new int[]{11, 22, 33, 44, 55, 66, 77}; + System.arraycopy(a, 2, b, 4, 3); + logger.info("b={}", Arrays.toString(b)); + + } +} diff --git a/group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/ArrayListTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java similarity index 94% rename from group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/ArrayListTest.java rename to group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java index 656ff54c06..9241fe72da 100644 --- a/group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/ArrayListTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java @@ -1,35 +1,35 @@ -package com.coding.basic; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Created by luoziyihao on 2/25/17. - */ -public class ArrayListTest { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - - private List list = new ArrayList(); - - @Before - public void before() { - - } - - @Test - public void add() throws Exception { - list.add(1); - } - - @Test - public void get() throws Exception { - add(); - logger.info("{}", list.get(0)); - } - +package com.coding.basic; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Created by luoziyihao on 2/25/17. + */ +public class ArrayListTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + private List list = new ArrayList(); + + @Before + public void before() { + + } + + @Test + public void add() throws Exception { + list.add(1); + } + + @Test + public void get() throws Exception { + add(); + logger.info("{}", list.get(0)); + } + } \ No newline at end of file diff --git a/group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/LinkedListTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java similarity index 97% rename from group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/LinkedListTest.java rename to group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java index 0424c2945e..e2007f6a2a 100644 --- a/group17/1204187480/code/homework/basic/src/test/java/com/coding/basic/LinkedListTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java @@ -61,18 +61,21 @@ public void removeFirstHalf() throws Exception { linkedList.removeFirstHalf(); Assert.assertEquals("[]", linkedList.toString()); } + @Test public void removeFirstHalf1() throws Exception { LinkedList linkedList = createAndFillLinkedList(1); linkedList.removeFirstHalf(); Assert.assertEquals("[1]", linkedList.toString()); } + @Test public void removeFirstHalf2() throws Exception { LinkedList linkedList = createAndFillLinkedList(2); linkedList.removeFirstHalf(); Assert.assertEquals("[2]", linkedList.toString()); } + @Test public void removeFirstHalf3() throws Exception { LinkedList linkedList = createAndFillLinkedList(3); @@ -102,37 +105,43 @@ public void remove1() throws Exception { list.remove(0, 0); Assert.assertEquals("[1,2,3,4]", list.toString()); } - @Test + + @Test public void remove2() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(0, 1); Assert.assertEquals("[2,3,4]", list.toString()); } - @Test + + @Test public void remove3() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(1, 0); Assert.assertEquals("[1,2,3,4]", list.toString()); } - @Test + + @Test public void remove4() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(1, 1); Assert.assertEquals("[1,3,4]", list.toString()); } -@Test + + @Test public void remove5() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(1, 3); Assert.assertEquals("[1]", list.toString()); } -@Test + + @Test public void remove6() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(1, 4); Assert.assertEquals("[1]", list.toString()); } -@Test + + @Test public void remove7() throws Exception { LinkedList list = createAndFillLinkedList(4); list.remove(1, 5); @@ -141,7 +150,7 @@ public void remove7() throws Exception { @Test public void getElements() throws Exception { - LinkedList listA= createAndFillLinkedList(0,8); + LinkedList listA = createAndFillLinkedList(0, 8); LinkedList listB = createAndFillLinkedList(4, 4); Assert.assertEquals("[4,5,6,7]", Arrays.toString(listA.getElements(listB))); diff --git a/group17/1204187480/code/homework/pom.xml b/group17/1204187480/code/homework/pom.xml index c8b94c2bc2..73e8c4160f 100644 --- a/group17/1204187480/code/homework/pom.xml +++ b/group17/1204187480/code/homework/pom.xml @@ -8,7 +8,7 @@ pom parent - basic + coding coderising From 398363a1198beb80872624e487a0e8e5d4d72647 Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Thu, 27 Apr 2017 09:47:19 +0800 Subject: [PATCH 137/151] add homework 0326 --- .../jvm/loader/ClassFileLoader.java | 19 + .../jvm/test/ClassFileloaderTest.java | 355 ++++++++++++++++++ .../com/coderising/jvm/test/EmployeeV1.java | 28 ++ .../src/main/java/com/coding/basic/Queue.java | 2 +- .../src/main/java/com/coding/basic/Stack.java | 2 + .../coding/basic/{ => array}/ArrayList.java | 5 +- .../com/coding/basic}/array/ArrayUtil.java | 2 +- .../coding/basic/linklist/LRUPageFrame.java | 57 +++ .../basic/linklist/LRUPageFrameTest.java | 34 ++ .../basic/{ => linklist}/LinkedList.java | 5 +- .../java/com/coding/basic/ArrayListTest.java | 1 + .../java/com/coding/basic/LinkedListTest.java | 1 + 12 files changed, 507 insertions(+), 4 deletions(-) create mode 100644 group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java create mode 100644 group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/ClassFileloaderTest.java create mode 100644 group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/EmployeeV1.java rename group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/{ => array}/ArrayList.java (96%) rename group17/1204187480/code/homework/{coderising/src/main/java/com/coderising => coding/src/main/java/com/coding/basic}/array/ArrayUtil.java (99%) create mode 100644 group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrame.java create mode 100644 group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrameTest.java rename group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/{ => linklist}/LinkedList.java (98%) diff --git a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..cb3c00fd9f --- /dev/null +++ b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.loader; + +/** + * Created by luoziyihao on 4/27/17. + */ +public class ClassFileLoader { + public void addClassPath(String path) { + + } + + + public String getClassPath() { + return null; + } + + public byte[] readBinaryCode(String className) { + return new byte[0]; + } +} diff --git a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/ClassFileloaderTest.java b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..b2dceda3e5 --- /dev/null +++ b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,355 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +//import com.coderising.jvm.clz.ClassFile; +//import com.coderising.jvm.clz.ClassIndex; +//import com.coderising.jvm.cmd.BiPushCmd; +//import com.coderising.jvm.cmd.ByteCodeCommand; +//import com.coderising.jvm.cmd.OneOperandCmd; +//import com.coderising.jvm.cmd.TwoOperandCmd; +//import com.coderising.jvm.constant.ClassInfo; +//import com.coderising.jvm.constant.ConstantPool; +//import com.coderising.jvm.constant.MethodRefInfo; +//import com.coderising.jvm.constant.NameAndTypeInfo; +//import com.coderising.jvm.constant.UTF8Info; +//import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +//import com.coderising.jvm.method.Method; + + + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path2 = "C:\temp"; + +// static ClassFile clzFile = null; +// static { +// ClassFileLoader loader = new ClassFileLoader(); +// loader.addClassPath(path1); +// String className = "com.coderising.jvm.test.EmployeeV1"; +// +// clzFile = loader.loadClass(className); +// +// } +// + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(10); +// Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); +// +// utf8Info = (UTF8Info) pool.getConstantInfo(11); +// Assert.assertEquals("Code", utf8Info.getValue()); +// } +// +// { +// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); +// Assert.assertEquals(3, methodRef.getClassInfoIndex()); +// Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); +// } +// +// { +// NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); +// Assert.assertEquals(9, nameAndType.getIndex1()); +// Assert.assertEquals(14, nameAndType.getIndex2()); +// } +// //抽查几个吧 +// { +// MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); +// Assert.assertEquals(1, methodRef.getClassInfoIndex()); +// Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); +// } +// +// { +// UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); +// Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); +// } +// } +// @Test +// public void testClassIndex(){ +// +// ClassIndex clzIndex = clzFile.getClzIndex(); +// ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); +// ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); +// +// +// 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); +// } +// +// @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/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/EmployeeV1.java b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java index 0f6caaec6f..e333496198 100644 --- a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Queue.java @@ -1,6 +1,6 @@ package com.coding.basic; -import java.util.Arrays; +import com.coding.basic.linklist.LinkedList; public class Queue { diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java index 7d91c326e0..7336dccfe9 100644 --- a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/Stack.java @@ -1,5 +1,7 @@ package com.coding.basic; +import com.coding.basic.array.ArrayList; + public class Stack { private ArrayList elementData = new ArrayList(); diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayList.java similarity index 96% rename from group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayList.java index 6ddf8cef58..cbe1f87a05 100644 --- a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/ArrayList.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayList.java @@ -1,4 +1,7 @@ -package com.coding.basic; +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; import java.util.Arrays; diff --git a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/array/ArrayUtil.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayUtil.java similarity index 99% rename from group17/1204187480/code/homework/coderising/src/main/java/com/coderising/array/ArrayUtil.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayUtil.java index 9aa6404d2a..42ec6efe57 100644 --- a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/array/ArrayUtil.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/array/ArrayUtil.java @@ -1,4 +1,4 @@ -package com.coderising.array; +package com.coding.basic.array; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrame.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..994a241a3d --- /dev/null +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,57 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + + } + + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + Node node = first; + while(node != null){ + buffer.append(node.pageNum); + + node = node.next; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } + + + +} diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrameTest.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/LinkedList.java b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LinkedList.java similarity index 98% rename from group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/LinkedList.java rename to group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LinkedList.java index c0cce5af0a..d9c4ee3c7b 100644 --- a/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/LinkedList.java +++ b/group17/1204187480/code/homework/coding/src/main/java/com/coding/basic/linklist/LinkedList.java @@ -1,4 +1,7 @@ -package com.coding.basic; +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; public class LinkedList implements List { diff --git a/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java index 9241fe72da..fba6895d09 100644 --- a/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/ArrayListTest.java @@ -1,5 +1,6 @@ package com.coding.basic; +import com.coding.basic.array.ArrayList; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; diff --git a/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java index e2007f6a2a..549553e696 100644 --- a/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java +++ b/group17/1204187480/code/homework/coding/src/test/java/com/coding/basic/LinkedListTest.java @@ -1,5 +1,6 @@ package com.coding.basic; +import com.coding.basic.linklist.LinkedList; import org.junit.Assert; import org.junit.Test; From 76b38962d8aa58d561e7fdb0378cc01f6c5cc834 Mon Sep 17 00:00:00 2001 From: luoziyihao Date: Thu, 27 Apr 2017 10:07:20 +0800 Subject: [PATCH 138/151] add homework 0326-1 --- .../jvm/loader/ClassFileLoader.java | 28 +++- .../1204187480/code/homework/parent/pom.xml | 150 +++++++++++++----- 2 files changed, 139 insertions(+), 39 deletions(-) diff --git a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java index cb3c00fd9f..a76de06aa1 100644 --- a/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group17/1204187480/code/homework/coderising/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -1,16 +1,42 @@ package com.coderising.jvm.loader; +import org.apache.commons.lang3.StringUtils; + +import java.util.HashSet; +import java.util.Set; + /** * Created by luoziyihao on 4/27/17. */ public class ClassFileLoader { + + private Set clzPaths; + public void addClassPath(String path) { + if (clzPaths == null) { + clzPaths = new HashSet<>(5); + } + if (StringUtils.isBlank(path)) { + return; + } + clzPaths.add(path); } + private static final String SPLIT = ";"; + public String getClassPath() { - return null; + StringBuilder classPath = new StringBuilder(); + + for (String e : clzPaths) { + classPath.append(e) + .append(SPLIT); + } + if (classPath.length() > 1) { + classPath.deleteCharAt(classPath.length() - 1); + } + return classPath.toString(); } public byte[] readBinaryCode(String className) { diff --git a/group17/1204187480/code/homework/parent/pom.xml b/group17/1204187480/code/homework/parent/pom.xml index ace9bf9cc5..4b82387454 100644 --- a/group17/1204187480/code/homework/parent/pom.xml +++ b/group17/1204187480/code/homework/parent/pom.xml @@ -8,18 +8,66 @@ 1.0-SNAPSHOT https://github.com/luoziyihao/coding2017 + + + alimaven + aliyun maven + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + true + + + + + + alimaven + aliyun maven + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + true + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot + + true + + + + + - UTF-8 UTF-8 UTF-8 - 1.8 + 1.8 + UTF-8 1.8 1.8 3.0 + 1.1.7 1.1.7 1.2 1.2.17 4.12 + 3.4 + 4.1 + 2.5 + 1.9.2 + 19.0 + 1.1.6 + 1.16.10 + 1.2.22 + 0.2.0 + 2.9.4 + @@ -41,6 +89,59 @@ ${log4j.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + commons-io + commons-io + ${commons-io.version} + + + commons-beanutils + commons-beanutils + ${commons-beanutils.version} + + + com.google.guava + guava + ${guava.version} + + + org.projectlombok + lombok + ${lombok.version} + + + joda-time + joda-time + ${joda-time.version} + + + io.reactivex + rxjava + ${rxjava.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + com.shekhargulati + strman + ${strman.version} + + + junit @@ -49,33 +150,6 @@ - - - alimaven - aliyun maven - http://maven.aliyun.com/nexus/content/groups/public/ - - true - - - true - - - - - - alimaven - aliyun maven - http://maven.aliyun.com/nexus/content/groups/public/ - - true - - - true - - - - ${project.artifactId} @@ -92,13 +166,13 @@ - - - - org.apache.maven.plugins - maven-surefire-report-plugin - 2.19.1 - - - + + + + + + + + + \ No newline at end of file From e351d94786bc3ba84566ab33c8902be433cb8c76 Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Thu, 27 Apr 2017 16:28:12 +0800 Subject: [PATCH 139/151] add mini-jvm test --- .../com/coderising/jvm/test/MiniJVMTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/MiniJVMTest.java diff --git a/liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/MiniJVMTest.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..787c0d954d --- /dev/null +++ b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} From 714956c1b4d376d48c7ca8c8dde13577de3abc35 Mon Sep 17 00:00:00 2001 From: Andy <14703250@qq.com> Date: Thu, 27 Apr 2017 20:13:45 +0800 Subject: [PATCH 140/151] Delete description.html --- .../275150374Learning/.idea/description.html | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 group01/275150374/275150374Learning/.idea/description.html diff --git a/group01/275150374/275150374Learning/.idea/description.html b/group01/275150374/275150374Learning/.idea/description.html deleted file mode 100644 index 0f928c44a1..0000000000 --- a/group01/275150374/275150374Learning/.idea/description.html +++ /dev/null @@ -1,15 +0,0 @@ -Simple Java application that includes a class with main() method \ No newline at end of file From c26fb8a02e8d17d30fcc383efcdad54b14881724 Mon Sep 17 00:00:00 2001 From: Andy <14703250@qq.com> Date: Thu, 27 Apr 2017 22:14:22 +0800 Subject: [PATCH 141/151] Delete description.html --- group15/1512_656512403/.idea/description.html | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 group15/1512_656512403/.idea/description.html diff --git a/group15/1512_656512403/.idea/description.html b/group15/1512_656512403/.idea/description.html deleted file mode 100644 index 0f928c44a1..0000000000 --- a/group15/1512_656512403/.idea/description.html +++ /dev/null @@ -1,15 +0,0 @@ -Simple Java application that includes a class with main() method \ No newline at end of file From d7eb24e25ea4b5ea09dc41eab549e41ab76828a6 Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Thu, 27 Apr 2017 22:15:33 +0800 Subject: [PATCH 142/151] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/basic/queue/CircleQueue.java | 37 +++++++++++----- .../coding/basic/queue/CircleQueueTest.java | 44 +++++++++++++++++++ 2 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueueTest.java diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java index b431db364f..8bd2577c53 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueue.java @@ -1,33 +1,46 @@ package com.coding.basic.queue; public class CircleQueue { - - private final static int DEFAULT_SIZE = 10; - + //用数组来保存循环队列的元素 - private Object[] elementData = new Object[DEFAULT_SIZE] ; - + private Object[] elementData ; + int size = 0; //队头 private int front = 0; //队尾 private int rear = 0; + public CircleQueue(int capacity){ + elementData = new Object[capacity]; + } public boolean isEmpty() { - return false; + return front == rear; } - + + public boolean isFull(){ + return size == elementData.length; + } public int size() { - return -1; + return size; } - - public void enQueue(E data) { - + if(isFull()){ + throw new RuntimeException("The queue is full"); + } + elementData[rear++] = data; + size++; } public E deQueue() { - return null; + if(isEmpty()){ + throw new RuntimeException("The queue is empty"); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front+1) % elementData.length; + size --; + return data; } } diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueueTest.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..7307eb77d4 --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,44 @@ +package com.coding.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 b4213a764d1eb59cc3eb4f962d7b6d94629227f7 Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Thu, 27 Apr 2017 22:30:36 +0800 Subject: [PATCH 143/151] remove virus --- .../com/coderising/download/net_multisoc.htm | 505 ------------------ 1 file changed, 505 deletions(-) delete mode 100644 group17/1282579502/src/com/coderising/download/net_multisoc.htm diff --git a/group17/1282579502/src/com/coderising/download/net_multisoc.htm b/group17/1282579502/src/com/coderising/download/net_multisoc.htm deleted file mode 100644 index 852129b19a..0000000000 --- a/group17/1282579502/src/com/coderising/download/net_multisoc.htm +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - -Java Examples - Multithreaded Server - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
- - - -
-
-
-
-
- - -
-
-
-

Java Examples - Multithreaded Server

-
-
-
Advertisements
- - -
-
- - -
-
-

Problem Description

-

How to create a multithreaded server ?

-

Solution

-

Following example demonstrates how to create a multithreaded server by using ssock.accept() method of Socket class and MultiThreadServer(socketname) method of ServerSocket class.

-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-public class MultiThreadServer implements Runnable {
-   Socket csocket;
-   MultiThreadServer(Socket csocket) {
-      this.csocket = csocket;
-   }
-   public static void main(String args[]) throws Exception { 
-      ServerSocket ssock = new ServerSocket(1234);
-      System.out.println("Listening");
-      
-      while (true) {
-         Socket sock = ssock.accept();
-         System.out.println("Connected");
-         new Thread(new MultiThreadServer(sock)).start();
-      }
-   }
-   public void run() {
-      try {
-         PrintStream pstream = new PrintStream(csocket.getOutputStream());
-         for (int i = 100; i >= 0; i--) {
-            pstream.println(i + " bottles of beer on the wall");
-         }
-         pstream.close();
-         csocket.close();
-      } catch (IOException e) {
-         System.out.println(e);
-      }
-   }
-}
-
-

Result

-

The above code sample will produce the following result.

-
-Listening
-Connected
-
-

Following is an another example of how to create a multithreaded server.

-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
- 
-public class NewClass {
-   ServerSocket myServerSocket;
-   boolean ServerOn = true;
-   public NewClass() { 
-      try {
-         myServerSocket = new ServerSocket(8888);
-      } catch(IOException ioe) { 
-         System.out.println("Could not create server socket on port 8888. Quitting.");
-         System.exit(-1);
-      } 
-		
-      Calendar now = Calendar.getInstance();
-      SimpleDateFormat formatter = new SimpleDateFormat(
-         "E yyyy.MM.dd 'at' hh:mm:ss a zzz");
-      System.out.println("It is now : " + formatter.format(now.getTime()));
-      
-      while(ServerOn) { 
-         try { 
-            Socket clientSocket = myServerSocket.accept();
-            ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
-            cliThread.start(); 
-         } catch(IOException ioe) { 
-            System.out.println("Exception found on accept. Ignoring. Stack Trace :"); 
-            ioe.printStackTrace(); 
-         }  
-      } 
-      try { 
-         myServerSocket.close(); 
-         System.out.println("Server Stopped"); 
-      } catch(Exception ioe) { 
-         System.out.println("Error Found stopping server socket"); 
-         System.exit(-1); 
-      } 
-   }
-	
-   public static void main (String[] args) { 
-      new NewClass();        
-   } 
-	
-   class ClientServiceThread extends Thread { 
-      Socket myClientSocket;
-      boolean m_bRunThread = true; 
-      public ClientServiceThread() { 
-         super(); 
-      } 
-		
-      ClientServiceThread(Socket s) { 
-         myClientSocket = s; 
-      } 
-		
-      public void run() { 
-         BufferedReader in = null; 
-         PrintWriter out = null; 
-         System.out.println(
-            "Accepted Client Address - " + myClientSocket.getInetAddress().getHostName());
-         try { 
-            in = new BufferedReader(
-               new InputStreamReader(myClientSocket.getInputStream()));
-            out = new PrintWriter(
-               new OutputStreamWriter(myClientSocket.getOutputStream()));
-            
-            while(m_bRunThread) { 
-               String clientCommand = in.readLine(); 
-               System.out.println("Client Says :" + clientCommand);
-               
-               if(!ServerOn) { 
-                  System.out.print("Server has already stopped"); 
-                  out.println("Server has already stopped"); 
-                  out.flush(); 
-                  m_bRunThread = false;
-               } 
-               if(clientCommand.equalsIgnoreCase("quit")) {
-                  m_bRunThread = false;
-                  System.out.print("Stopping client thread for client : ");
-               } else if(clientCommand.equalsIgnoreCase("end")) {
-                  m_bRunThread = false;
-                  System.out.print("Stopping client thread for client : ");
-                  ServerOn = false;
-               } else {
-                  out.println("Server Says : " + clientCommand);
-                  out.flush(); 
-               } 
-            } 
-         } catch(Exception e) { 
-            e.printStackTrace(); 
-         } 
-         finally { 
-            try { 
-               in.close(); 
-               out.close(); 
-               myClientSocket.close(); 
-               System.out.println("...Stopped"); 
-            } catch(IOException ioe) { 
-               ioe.printStackTrace(); 
-            } 
-         } 
-      } 
-   } 
-}
-
-
- - - -
java_networking.htm
-
- -
-
Advertisements
- - -
-
-
-
-
- -
- - -
-
- - -
-
- - -
-
-
-
-
-
- - -
- - - - - - - - - \ No newline at end of file From 809a3893245992e90e524046c3564ba707e89bcc Mon Sep 17 00:00:00 2001 From: xukai Date: Fri, 28 Apr 2017 08:01:15 +0800 Subject: [PATCH 144/151] jvm5 --- group19/527220084/lite-file-downloader.zip | Bin 0 -> 12749 bytes group19/527220084/lite-struts-tdd.zip | Bin 0 -> 290775 bytes .../xukai/coderising/queue/CircleQueue.java | 81 +++++++++++ .../org/xukai/coderising/queue/Josephus.java | 49 +++++++ .../xukai/coderising/queue/JosephusTest.java | 29 ++++ .../coderising/queue/QueueWithTwoStacks.java | 83 +++++++++++ .../java/org/xukai/jvm/cmd/BiPushCmd.java | 13 +- .../org/xukai/jvm/cmd/ByteCodeCommand.java | 41 +++++- .../java/org/xukai/jvm/cmd/GetFieldCmd.java | 20 ++- .../org/xukai/jvm/cmd/GetStaticFieldCmd.java | 7 + .../org/xukai/jvm/cmd/InvokeSpecialCmd.java | 25 +++- .../org/xukai/jvm/cmd/InvokeVirtualCmd.java | 9 +- .../main/java/org/xukai/jvm/cmd/LdcCmd.java | 22 ++- .../java/org/xukai/jvm/cmd/NewObjectCmd.java | 12 +- .../java/org/xukai/jvm/cmd/NoOperandCmd.java | 124 ++++++++++++++++- .../java/org/xukai/jvm/cmd/PutFieldCmd.java | 18 +++ .../java/org/xukai/jvm/cmd/TwoOperandCmd.java | 1 - .../org/xukai/jvm/engine/ExecutionResult.java | 57 ++++++++ .../org/xukai/jvm/engine/ExecutorEngine.java | 58 ++++++++ .../main/java/org/xukai/jvm/engine/Heap.java | 39 ++++++ .../java/org/xukai/jvm/engine/JavaObject.java | 72 ++++++++++ .../java/org/xukai/jvm/engine/MethodArea.java | 75 ++++++++++ .../java/org/xukai/jvm/engine/MiniJVM.java | 30 ++++ .../java/org/xukai/jvm/engine/StackFrame.java | 130 ++++++++++++++++++ .../java/org/xukai/jvm/method/Method.java | 57 ++++++++ 25 files changed, 1038 insertions(+), 14 deletions(-) create mode 100644 group19/527220084/lite-file-downloader.zip create mode 100644 group19/527220084/lite-struts-tdd.zip create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/CircleQueue.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/Josephus.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/JosephusTest.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/QueueWithTwoStacks.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutionResult.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutorEngine.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/Heap.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/JavaObject.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MethodArea.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MiniJVM.java create mode 100644 group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/StackFrame.java diff --git a/group19/527220084/lite-file-downloader.zip b/group19/527220084/lite-file-downloader.zip new file mode 100644 index 0000000000000000000000000000000000000000..69153a25c26a6d85f54d17a6448aaa3c63304d90 GIT binary patch literal 12749 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 literal 0 HcmV?d00001 diff --git a/group19/527220084/lite-struts-tdd.zip b/group19/527220084/lite-struts-tdd.zip new file mode 100644 index 0000000000000000000000000000000000000000..e27ef4ec8123632f4c535e8b3a9c132dbdf3388f GIT binary patch literal 290775 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
tWYZ;23yk<{Te?pZoJ$i?! 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%0A5E(t?jS@6O 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
7cl`hMp^<@6p_(cD3D{Tbw9HCOR6dir6$ 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
  • *4L_SDzQf%?L`d1qZ?_eo)vLKqv9)h-+2nw{K(7$*&yCG`Q4B%AyC{P^RSbu@tG- zkW7M8zvePF$E%-h7=@Bv`zK&SbFEFV+(>e$bs;|>Nl(>%I*OB!DEZdC+k&B}qc`OZS&^fp z?(|s8?Hdz|rec5EIep^KEpdx9HM&9`GsI&J!elM@PCV7(O78AAVd-Rt<(ihDqm3Aw zccB1f`R4(Ih^hr!sTyI)=33HGU}*vZLhO7^p>BuIrz!!K2@YyLsDvVlb9|WFZ+g=x zIlJjv`vnEWS1r8Lbarj%V=o`c(%-_2FTl_}{*|fHCelt0Kvt4qs7(h9pSx?Xk@O?kT5HNtEuv`@TWWb)q>fO8!VY|%$e)U05APa8RJr7BeYXLZ zE$~@&Sc&eHq$%8(K4=MjsK>S6PBdORZXgd*#8uaWN%4&p&vgvXhc{c#x$*+Kbyz^= z22oA)C~s5(x<*plGzQEFL`~NB6%})E)2+f@2X}ujatVNC`xL~j)Iqew)UmG z+sqigQn)7weeE4CtB&)&@Ka^G|7St|&o}PQ4-fZ0hq`*NuTAeyZjbk&HpANq^S8he zOE2Z#{;>TD6~OGr=>8P}n*=G6b-(Do(JXL`_1Egm2E8Y$36jX<{y(!_?te5rv~4Ur z{)!_G@k+?uqNvg{tmo*uKP}lP3`H?vyZlHbVjJ9L)n7+?cobarM{}fo-0)dW3j{~g z207Vor(q*8FU!BGew$iXP)fz_S|LFVkKdYW7t7q(JB}vqQ#Kn?sfvrPh~bIng%^5c z4eOJH81klI^W=pkWtOp$bmFxxk-w;44$XqK4$DhDI`i@$@WXcVhsYPTFWoK}U)Fy1 z47*4m5w$s$kXNn-@!CFs#{3=`d}+5I?;1WD=1!B`^s{F2{-vBe2ftQG*E1ms`km!9 z{};;h{2wXjKZrD&r-Oa$+iLV~3e0dTC0_*BmaH@whxN6MA`H=EdrllwnQ#60`glqU z10b5mE1*%rx6=Ckpr9BJIQtuT0)YeezHe~pDiIgxC9d_!I1>1bN-U(sAVse&%{Op5 zM#Kn;`cj&Km#iv+@Djx#`q(bUHz!F8S2P5p>!hg|dSefBPFR<;Vg+C4 z5drH=2X|43 z%YDk--o}*O*4)W~m5YsojR#^Ku1|UW+TD1Hxc=JR_)SCVuz&FSr+XbwCH+EhpMsaa z5ZvFSrv0xa{fXy375NJleG00H{+0*1a(?x%MgARto=W=_*`A^^zks^mq@epxr2RK+ z_f*a=tmkQJ`wQ#&P0srNM9%*}ex8c@l`B78@r(VI1G!2w{P&{%rv`te5l>eQztV`` zbY${R#63wWp7!Y1AU%ydzm^}riOBMwi};^C`Af_bAO0(h{U(0ve + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + private int count = 0; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return count == 0; + + } + + public int size() { + return count; + } + + + + public void enQueue(E data) { + if (count == DEFAULT_SIZE ) { + throw new RuntimeException(); + } + elementData[front] = data; + front = (front + 1) % DEFAULT_SIZE; + count++; + } + + public E deQueue() { + if (count == 0) { + return null; + } + count--; + E e = (E)elementData[rear]; + rear = (rear + 1) % DEFAULT_SIZE; + return e; + } + + public static void main(String[] args) { + CircleQueue queue = new CircleQueue<>(); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + queue.enQueue(4); + queue.enQueue(5); + queue.enQueue(6); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue());System.out.println(queue.deQueue());System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + queue.enQueue(7); + queue.enQueue(8); + queue.enQueue(9); + queue.enQueue(0); + queue.enQueue(1); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/Josephus.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/Josephus.java new file mode 100644 index 0000000000..a59696088a --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/Josephus.java @@ -0,0 +1,49 @@ +package org.xukai.coderising.queue; + +import com.google.common.base.Preconditions; + +import java.util.ArrayDeque; +import java.util.ArrayList; +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){ + Preconditions.checkArgument(n > 0); + ArrayList deadList = new ArrayList<>(); + ArrayDeque deque1 = new ArrayDeque<>(); + ArrayDeque deque2 = new ArrayDeque<>(); + for (int i = 0; i < n; i++) { + deque1.offer(i); + } + int count = 0; + while(n >= m){ + if (deque1.isEmpty()) { + while (!deque2.isEmpty()){ + deque1.offer(deque2.poll()); + } + } + count++; + if (count == m) { + deadList.add(deque1.poll()); + count = 0; + n--; + continue; + } + deque2.offer(deque1.poll()); + + } + + return deadList; + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/JosephusTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/JosephusTest.java new file mode 100644 index 0000000000..9a1a0a4dcb --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/JosephusTest.java @@ -0,0 +1,29 @@ +package org.xukai.coderising.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]", Josephus.execute(7, 2).toString()); + + + + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/QueueWithTwoStacks.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..f1a89a82a9 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/queue/QueueWithTwoStacks.java @@ -0,0 +1,83 @@ +package org.xukai.coderising.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 stack1.isEmpty(); + } + + + + public int size() { + return stack1.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (stack1.isEmpty()) { + return null; + } + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + E e = stack2.pop(); + while (!stack2.isEmpty()) { + stack1.push(stack2.pop()); + } + return e; + } + + public static void main(String[] args) { + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + queue.enQueue(4); + queue.enQueue(5); + queue.enQueue(6); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue());System.out.println(queue.deQueue());System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + queue.enQueue(7); + queue.enQueue(8); + queue.enQueue(9); + queue.enQueue(0); + queue.enQueue(1); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + + + } + + } + diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java index bd1eb4bf11..409291ec84 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/BiPushCmd.java @@ -3,6 +3,10 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.Heap; +import org.xukai.jvm.engine.JavaObject; +import org.xukai.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -16,7 +20,12 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } - - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject javaObject = Heap.getInstance().newInt(getOperand()); + frame.getOprandStack().push(javaObject); + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java index edb68e1256..4c888e8e36 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/ByteCodeCommand.java @@ -4,6 +4,8 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantInfo; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.StackFrame; import java.util.HashMap; import java.util.Map; @@ -14,7 +16,42 @@ public abstract class ByteCodeCommand { String opCode; ClassFile clzFile; private int offset; - + + 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"; + private static Map codeMap = new HashMap(); static{ @@ -125,5 +162,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame, ExecutionResult result); } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java index faa268b0d2..8e100b59a5 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetFieldCmd.java @@ -3,6 +3,10 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.FieldRefInfo; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.JavaObject; +import org.xukai.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -13,10 +17,22 @@ public GetFieldCmd(ClassFile clzFile, String opCode) { @Override public String toString(ConstantPool pool) { - return super.getOperandAsField(pool); + return super.getOperandAsField(clzFile.getConstantPool()); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + + } } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java index 4112f7cc56..1af0fa9e80 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/GetStaticFieldCmd.java @@ -3,6 +3,8 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -17,4 +19,9 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java index 7dd0b62407..86f104130a 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeSpecialCmd.java @@ -2,7 +2,13 @@ import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.ConstantInfo; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.MethodRefInfo; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.MethodArea; +import org.xukai.jvm.engine.StackFrame; +import org.xukai.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -17,6 +23,23 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int index = getIndex(); + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(index); + String methodName = methodRefInfo.getMethodName(); + String paramAndReturnType = methodRefInfo.getParamAndReturnType(); + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java index 77ba5c7460..b6c8505295 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/InvokeVirtualCmd.java @@ -3,6 +3,8 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.StackFrame; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -16,7 +18,10 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java index 2d8b1ae2f3..db9aba648d 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/LdcCmd.java @@ -5,6 +5,10 @@ import org.xukai.jvm.constant.ConstantInfo; import org.xukai.jvm.constant.ConstantPool; import org.xukai.jvm.constant.StringInfo; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.Heap; +import org.xukai.jvm.engine.JavaObject; +import org.xukai.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -26,5 +30,21 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantInfo constantInfo = getConstantPool().getConstantInfo(this.getOperand()); + if(constantInfo instanceof StringInfo){ + StringInfo strInfo = (StringInfo)constantInfo; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java index 0ac1b33832..30174639a2 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NewObjectCmd.java @@ -2,7 +2,11 @@ import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.ClassInfo; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.Heap; +import org.xukai.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd { @@ -16,5 +20,11 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassInfo classInfo = (ClassInfo) getConstantInfo(getIndex()); + Heap.getInstance().newObject(classInfo.getClassName()); + } + + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java index 63683e3865..658375f3bf 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/NoOperandCmd.java @@ -3,6 +3,10 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.Heap; +import org.xukai.jvm.engine.JavaObject; +import org.xukai.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand { @@ -15,8 +19,124 @@ public String toString(ConstantPool pool) { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } - - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + } + + public int getLength(){ return 1; } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java index 0a5987e4c3..fa6bdc7d0e 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/PutFieldCmd.java @@ -3,6 +3,10 @@ import org.xukai.jvm.clz.ClassFile; import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.FieldRefInfo; +import org.xukai.jvm.engine.ExecutionResult; +import org.xukai.jvm.engine.JavaObject; +import org.xukai.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -16,5 +20,19 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + int index = getIndex(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + String fieldName = info.getFieldName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = info.getFieldType(); + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + } + } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java index b423f989ae..c221302acd 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/cmd/TwoOperandCmd.java @@ -50,7 +50,6 @@ protected String getOperandAsClassInfo(ConstantPool pool){ 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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutionResult.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..0baa5280de --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutionResult.java @@ -0,0 +1,57 @@ +package org.xukai.jvm.engine; + + +import org.xukai.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutorEngine.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..6a0bdc50f3 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/ExecutorEngine.java @@ -0,0 +1,58 @@ +package org.xukai.jvm.engine; + +import org.xukai.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + StackFrame MainFrame = StackFrame.create(mainMethod); + stack.push(MainFrame); + while(!stack.empty()){ + StackFrame currentFrame = stack.peek(); + ExecutionResult result = currentFrame.execute(); + if (result.isPauseAndRunNewFrame()) { + StackFrame nextFrame = currentFrame.create(result.getNextMethod()); + nextFrame.setCallerFrame(currentFrame); + setupFunctionCallParams(currentFrame, nextFrame); + stack.push(nextFrame); + } else { + stack.pop(); + } + } + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + List parameterList = nextFrame.getMethod().getParameterList(); + if (parameterList.size() > 0) { + + } + ArrayList localVariabs = new ArrayList<>(); + for (int i = 0; i < parameterList.size() + 1; i++) { + JavaObject javaObject = currentFrame.getOprandStack().pop(); + localVariabs.add(javaObject); + } + ArrayList params = new ArrayList<>(); + for (int i = localVariabs.size(); i > 0; i--) { + params.add(localVariabs.get(i)); + } + nextFrame.setLocalVariableTable(params); + + + + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/Heap.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/Heap.java new file mode 100644 index 0000000000..0e46ee43c9 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package org.xukai.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/JavaObject.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..9a544321c0 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/JavaObject.java @@ -0,0 +1,72 @@ +package org.xukai.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MethodArea.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..9188070ce4 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MethodArea.java @@ -0,0 +1,75 @@ +package org.xukai.jvm.engine; + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.MethodRefInfo; +import org.xukai.jvm.loader.ClassFileLoader; +import org.xukai.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + ClassFile clzFile = this.findClassFile(className); + return clzFile.getMethod(methodName,paramAndReturnType); + } + + + public Method getMethod(MethodRefInfo methodRef){ + String methodName = methodRef.getMethodName(); + String paramAndReturnType = methodRef.getParamAndReturnType(); + for (String clzName : map.keySet()) { + Method method = getMethod(clzName, methodName, paramAndReturnType); + if (method != null) { + return method; + } + } + return null; + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MiniJVM.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..7ea53b7f32 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/engine/MiniJVM.java @@ -0,0 +1,30 @@ +package org.xukai.jvm.engine; + + +import org.xukai.jvm.loader.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java index 27585d73b1..0424356553 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java @@ -8,6 +8,9 @@ import org.xukai.jvm.constant.UTF8Info; import org.xukai.jvm.loader.ByteCodeIterator; +import java.util.ArrayList; +import java.util.List; + public class Method { private int accessFlag; @@ -83,5 +86,59 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ } + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getMethodDescription(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } + } From 4c410e3b5ae091b40e776be347a901dce4392d1c Mon Sep 17 00:00:00 2001 From: chzh88 Date: Fri, 28 Apr 2017 09:39:48 +0800 Subject: [PATCH 145/151] delete virus --- group15/1512_656512403/.idea/description.html | 15 - .../com/coderising/download/net_multisoc.htm | 505 ------------------ 2 files changed, 520 deletions(-) delete mode 100644 group15/1512_656512403/.idea/description.html delete mode 100644 group17/1282579502/src/com/coderising/download/net_multisoc.htm diff --git a/group15/1512_656512403/.idea/description.html b/group15/1512_656512403/.idea/description.html deleted file mode 100644 index 0f928c44a1..0000000000 --- a/group15/1512_656512403/.idea/description.html +++ /dev/null @@ -1,15 +0,0 @@ -Simple Java application that includes a class with main() method \ No newline at end of file diff --git a/group17/1282579502/src/com/coderising/download/net_multisoc.htm b/group17/1282579502/src/com/coderising/download/net_multisoc.htm deleted file mode 100644 index 852129b19a..0000000000 --- a/group17/1282579502/src/com/coderising/download/net_multisoc.htm +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - - -Java Examples - Multithreaded Server - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    -
    -
    - - - -
    -
    -
    -
    -
    - - -
    -
    -
    -

    Java Examples - Multithreaded Server

    -
    -
    -
    Advertisements
    - - -
    -
    - - -
    -
    -

    Problem Description

    -

    How to create a multithreaded server ?

    -

    Solution

    -

    Following example demonstrates how to create a multithreaded server by using ssock.accept() method of Socket class and MultiThreadServer(socketname) method of ServerSocket class.

    -
    -import java.io.IOException;
    -import java.io.PrintStream;
    -import java.net.ServerSocket;
    -import java.net.Socket;
    -
    -public class MultiThreadServer implements Runnable {
    -   Socket csocket;
    -   MultiThreadServer(Socket csocket) {
    -      this.csocket = csocket;
    -   }
    -   public static void main(String args[]) throws Exception { 
    -      ServerSocket ssock = new ServerSocket(1234);
    -      System.out.println("Listening");
    -      
    -      while (true) {
    -         Socket sock = ssock.accept();
    -         System.out.println("Connected");
    -         new Thread(new MultiThreadServer(sock)).start();
    -      }
    -   }
    -   public void run() {
    -      try {
    -         PrintStream pstream = new PrintStream(csocket.getOutputStream());
    -         for (int i = 100; i >= 0; i--) {
    -            pstream.println(i + " bottles of beer on the wall");
    -         }
    -         pstream.close();
    -         csocket.close();
    -      } catch (IOException e) {
    -         System.out.println(e);
    -      }
    -   }
    -}
    -
    -

    Result

    -

    The above code sample will produce the following result.

    -
    -Listening
    -Connected
    -
    -

    Following is an another example of how to create a multithreaded server.

    -
    -import java.io.BufferedReader;
    -import java.io.IOException;
    -import java.io.InputStreamReader;
    -import java.io.OutputStreamWriter;
    -import java.io.PrintWriter;
    -
    -import java.net.ServerSocket;
    -import java.net.Socket;
    -import java.text.SimpleDateFormat;
    -import java.util.Calendar;
    - 
    -public class NewClass {
    -   ServerSocket myServerSocket;
    -   boolean ServerOn = true;
    -   public NewClass() { 
    -      try {
    -         myServerSocket = new ServerSocket(8888);
    -      } catch(IOException ioe) { 
    -         System.out.println("Could not create server socket on port 8888. Quitting.");
    -         System.exit(-1);
    -      } 
    -		
    -      Calendar now = Calendar.getInstance();
    -      SimpleDateFormat formatter = new SimpleDateFormat(
    -         "E yyyy.MM.dd 'at' hh:mm:ss a zzz");
    -      System.out.println("It is now : " + formatter.format(now.getTime()));
    -      
    -      while(ServerOn) { 
    -         try { 
    -            Socket clientSocket = myServerSocket.accept();
    -            ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
    -            cliThread.start(); 
    -         } catch(IOException ioe) { 
    -            System.out.println("Exception found on accept. Ignoring. Stack Trace :"); 
    -            ioe.printStackTrace(); 
    -         }  
    -      } 
    -      try { 
    -         myServerSocket.close(); 
    -         System.out.println("Server Stopped"); 
    -      } catch(Exception ioe) { 
    -         System.out.println("Error Found stopping server socket"); 
    -         System.exit(-1); 
    -      } 
    -   }
    -	
    -   public static void main (String[] args) { 
    -      new NewClass();        
    -   } 
    -	
    -   class ClientServiceThread extends Thread { 
    -      Socket myClientSocket;
    -      boolean m_bRunThread = true; 
    -      public ClientServiceThread() { 
    -         super(); 
    -      } 
    -		
    -      ClientServiceThread(Socket s) { 
    -         myClientSocket = s; 
    -      } 
    -		
    -      public void run() { 
    -         BufferedReader in = null; 
    -         PrintWriter out = null; 
    -         System.out.println(
    -            "Accepted Client Address - " + myClientSocket.getInetAddress().getHostName());
    -         try { 
    -            in = new BufferedReader(
    -               new InputStreamReader(myClientSocket.getInputStream()));
    -            out = new PrintWriter(
    -               new OutputStreamWriter(myClientSocket.getOutputStream()));
    -            
    -            while(m_bRunThread) { 
    -               String clientCommand = in.readLine(); 
    -               System.out.println("Client Says :" + clientCommand);
    -               
    -               if(!ServerOn) { 
    -                  System.out.print("Server has already stopped"); 
    -                  out.println("Server has already stopped"); 
    -                  out.flush(); 
    -                  m_bRunThread = false;
    -               } 
    -               if(clientCommand.equalsIgnoreCase("quit")) {
    -                  m_bRunThread = false;
    -                  System.out.print("Stopping client thread for client : ");
    -               } else if(clientCommand.equalsIgnoreCase("end")) {
    -                  m_bRunThread = false;
    -                  System.out.print("Stopping client thread for client : ");
    -                  ServerOn = false;
    -               } else {
    -                  out.println("Server Says : " + clientCommand);
    -                  out.flush(); 
    -               } 
    -            } 
    -         } catch(Exception e) { 
    -            e.printStackTrace(); 
    -         } 
    -         finally { 
    -            try { 
    -               in.close(); 
    -               out.close(); 
    -               myClientSocket.close(); 
    -               System.out.println("...Stopped"); 
    -            } catch(IOException ioe) { 
    -               ioe.printStackTrace(); 
    -            } 
    -         } 
    -      } 
    -   } 
    -}
    -
    -
    - - - -
    java_networking.htm
    -
    - -
    -
    Advertisements
    - - -
    -
    -
    -
    -
    - -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -
    - - -
    - - - - - -
  • - - - \ No newline at end of file From 6dbfb215c05b579b6ecebbd129ee26474f24daa0 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 28 Apr 2017 16:21:31 +0800 Subject: [PATCH 146/151] update queue --- .../coding2017/queue/CircleQueue.java | 54 +++++++++++++++++-- .../HarryHook/coding2017/queue/Josephus.java | 26 ++++++++- .../coding2017/queue/QueueWithTwoStacks.java | 39 ++++++++++++-- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java index cd82fb2550..8ab6f440f4 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java @@ -1,5 +1,7 @@ package com.github.HarryHook.coding2017.queue; +import java.util.NoSuchElementException; + /** * 用数组实现循环队列 * @@ -16,23 +18,65 @@ public class CircleQueue { // 队头 private int front = 0; - // 队尾 + // 队尾,最后一个有效元素的下一个元素 private int rear = 0; - + // 队内元素个数 + private int size = 0; public boolean isEmpty() { + if(rear == front) { //但不一定为0 + return true; + } return false; } - public int size() { - return -1; + public int size() { + return size; } public void enQueue(E data) { + if((rear + 1) % DEFAULT_SIZE != front) { //队列未满 + elementData[rear] = data; + rear = (rear + 1) % DEFAULT_SIZE; + size++; + } } public E deQueue() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("Queue underflow"); + } + E data = (E) elementData[front]; + front = (front + 1) % DEFAULT_SIZE; + size--; + return data; + } + public static void main(String[] args) { + CircleQueue queue = new CircleQueue<>(); + queue.enQueue(1); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + queue.enQueue(1); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + queue.enQueue(1); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + System.out.println("queue.deQueue()= " + queue.deQueue()); + System.out.println("queue.deQueue()= " + queue.deQueue()); + System.out.println("queue.deQueue()= " + queue.deQueue()); + System.out.println("queue.deQueue()= " + queue.deQueue()); + System.out.println("queue.size= " + queue.size()); + queue.enQueue(3); + queue.enQueue(3); + queue.enQueue(1); + queue.enQueue(1); + queue.enQueue(2); + System.out.println("queue.rear= " + queue.rear); + System.out.println("queue.front= " + queue.front); } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java index 7b5fe53f5e..b919fbe94c 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java @@ -1,7 +1,10 @@ package com.github.HarryHook.coding2017.queue; +import java.util.ArrayList; import java.util.List; +import com.sun.corba.se.spi.orb.StringPair; + /** * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 @@ -12,7 +15,28 @@ public class Josephus { public static List execute(int n, int m) { - return null; + Queue queue = new Queue<>(); + List list = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + int i = 0; + while (!(queue.isEmpty())) { + int j = queue.deQueue(); + if (++i % m == 0) { + list.add(j); + } else { + queue.enQueue(j); + } + } + return list; + } + + public static void main(String[] args) { + Josephus circle = new Josephus(); + List list = circle.execute(41, 3); + System.out.println(list); } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java index c72abadcd2..494ad7452e 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java @@ -14,24 +14,55 @@ public class QueueWithTwoStacks { private Stack stack2; public QueueWithTwoStacks() { - stack1 = new Stack(); - stack2 = new Stack(); + stack1 = new Stack(); // 入队 + stack2 = new Stack(); // 出队 } public boolean isEmpty() { + if (stack1.isEmpty() && stack2.isEmpty()) { + return true; + } return false; } public int size() { - return -1; + return stack1.size() + stack2.size(); } public void enQueue(E item) { + stack1.push(item); } public E deQueue() { - return null; + + if (isEmpty()) { + throw new RuntimeException("queue is empty"); + } + + while (!(stack1.isEmpty())) { + stack2.push(stack1.pop()); + } + E popItem = stack2.pop(); + while (!(stack2.isEmpty())) { + stack1.push(stack2.pop()); + } + + return popItem; + } + + public static void main(String[] args) { + QueueWithTwoStacks stackQueue = new QueueWithTwoStacks<>(); + stackQueue.enQueue(5); + stackQueue.enQueue(36); + stackQueue.enQueue(1); + stackQueue.enQueue(2); + stackQueue.deQueue(); + stackQueue.enQueue(3); + while (!(stackQueue.isEmpty())) { + System.out.println(stackQueue.deQueue()); + } + } } From 33943f194171b679b8639bde3e812492b7e3bc53 Mon Sep 17 00:00:00 2001 From: onlyliuxin <14703250@qq.com> Date: Wed, 3 May 2017 20:09:34 +0800 Subject: [PATCH 147/151] =?UTF-8?q?jvm=E7=AC=AC6=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BB=93=E6=9E=84=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/basic/stack/QuickMinStack.java | 19 +++++++ .../basic/stack/StackWithTwoQueues.java | 16 ++++++ .../basic/stack/TwoStackInOneArray.java | 57 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/stack/QuickMinStack.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/stack/StackWithTwoQueues.java create mode 100644 liuxin/data-structure/assignment/src/com/coding/basic/stack/TwoStackInOneArray.java diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/QuickMinStack.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..f391d92b8f --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,19 @@ +package com.coding.basic.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + public void push(int data){ + + } + public int pop(){ + return -1; + } + public int findMin(){ + return -1; + } +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackWithTwoQueues.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..d0ab4387d2 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,16 @@ +package com.coding.basic.stack; + + +public class StackWithTwoQueues { + + + public void push(int data) { + + } + + public int pop() { + return -1; + } + + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/TwoStackInOneArray.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..e86d056a24 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return null; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + return null; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return null; + } + +} From 315b113160291bce3b868667f515be66821ba1c2 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 3 May 2017 21:50:39 +0800 Subject: [PATCH 148/151] add jvm_5 and queue --- .../coding2017/jvm/attr/CodeAttr.java | 2 +- .../coding2017/jvm/clz/ClassFile.java | 12 +- .../coding2017/jvm/cmd/BiPushCmd.java | 35 ++- .../coding2017/jvm/cmd/ByteCodeCommand.java | 242 ++++++++++-------- .../coding2017/jvm/cmd/CommandParser.java | 59 +---- .../coding2017/jvm/cmd/GetFieldCmd.java | 20 +- .../coding2017/jvm/cmd/GetStaticFieldCmd.java | 39 ++- .../coding2017/jvm/cmd/InvokeSpecialCmd.java | 38 ++- .../coding2017/jvm/cmd/InvokeVirtualCmd.java | 78 +++++- .../HarryHook/coding2017/jvm/cmd/LdcCmd.java | 55 ++-- .../coding2017/jvm/cmd/NewObjectCmd.java | 41 ++- .../coding2017/jvm/cmd/NoOperandCmd.java | 140 +++++++++- .../coding2017/jvm/cmd/PutFieldCmd.java | 40 ++- .../coding2017/jvm/cmd/TwoOperandCmd.java | 105 ++++---- .../coding2017/jvm/constant/ClassInfo.java | 7 +- .../coding2017/jvm/constant/ConstantInfo.java | 29 ++- .../jvm/engine/ExecutionResult.java | 53 ++++ .../coding2017/jvm/engine/ExecutorEngine.java | 78 ++++++ .../HarryHook/coding2017/jvm/engine/Heap.java | 43 ++++ .../coding2017/jvm/engine/JavaObject.java | 82 ++++++ .../coding2017/jvm/engine/MethodArea.java | 83 ++++++ .../coding2017/jvm/engine/MiniJVM.java | 28 ++ .../coding2017/jvm/engine/OperandStack.java | 29 +++ .../coding2017/jvm/engine/StackFrame.java | 116 +++++++++ .../coding2017/jvm/method/Method.java | 82 +++++- .../coding2017/jvm/test/MiniJVMTest.java | 29 +++ 26 files changed, 1226 insertions(+), 339 deletions(-) create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutionResult.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutorEngine.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/Heap.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/JavaObject.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MethodArea.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MiniJVM.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/OperandStack.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/StackFrame.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/MiniJVMTest.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 9ecd803572..00135d59c7 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 @@ -99,7 +99,7 @@ private void setStackMapTable(StackMapTable t) { public String toString(ConstantPool pool) { StringBuffer buffer = new StringBuffer(); 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"); - } - - + String opCode; + ClassFile clzFile; + private int offset; - + 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"; - protected ByteCodeCommand(ClassFile clzFile, String opCode){ - this.clzFile = clzFile; - this.opCode = opCode; - } - - protected ClassFile getClassFile() { - return clzFile; - } - - public int getOffset() { - return offset; - } + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; - 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 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"; + private static Map codeMap = new HashMap(); - 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; + 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 getReadableCodeText() { + String txt = codeMap.get(opCode); + if (txt == null) { + return opCode; } - - //public abstract void execute(StackFrame frame,FrameResult result); + return txt; + } + + public abstract void execute(StackFrame frame, ExecutionResult 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 index b982fa7aa4..7ead19d285 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 @@ -7,41 +7,6 @@ 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) { if ((codes == null) || (codes.length() == 0) || (codes.length() % 2) != 0) { @@ -57,51 +22,53 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { while (iter.hasNext()) { String opCode = iter.next2CharAsString(); - if (new_object.equals(opCode)) { + if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.ldc.equals(opCode)) { LdcCmd cmd = new LdcCmd(clzFile, opCode); cmd.setOperand(iter.next2CharAsInt()); cmds.add(cmd); - } else if (bipush.equals(opCode)) { + } else if (ByteCodeCommand.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)) { + } else if (ByteCodeCommand.dup.equals(opCode) || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) || ByteCodeCommand.astore_1.equals(opCode)) { NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); cmds.add(cmd); 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 index ec34e7b4a7..e9be866ec6 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -10,9 +14,21 @@ public GetFieldCmd(ClassFile clzFile, String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); - 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 index 1090e17374..eb943f2422 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java @@ -1,24 +1,39 @@ 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; - +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.Heap; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { - public GetStaticFieldCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); - - } + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); - @Override - public String toString(ConstantPool pool) { - - return super.getOperandAsField(pool); + if ("java/lang/System".equals(className) && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)) { + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); } + // TODO 处理非System.out的情况 + } } \ 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 index 4afc337f47..3c847d847e 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java @@ -3,21 +3,39 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; - +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.MethodArea; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; +import com.github.HarryHook.coding2017.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { - public InvokeSpecialCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); - - } + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if (methodRefInfo.getClassName().equals("java/lang/Object") && methodRefInfo.getMethodName().equals("")) { + return; - @Override - public String toString(ConstantPool pool) { - - return super.getOperandAsMethod(pool); } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); - + } } \ 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 index 6b494dceda..b94dba6f95 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java @@ -1,21 +1,81 @@ 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; +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.MethodArea; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; +import com.github.HarryHook.coding2017.jvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { - public InvokeVirtualCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName) { + return "java/io/PrintStream".equals(className) && "println".equals(methodName); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + // 先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if (isSystemOutPrintlnMethod(className, methodName)) { + JavaObject jo = (JavaObject) frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------" + value + "----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + // 注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while (currentClassName != null) { + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), methodRefInfo.getParamAndReturnType()); + if (m != null) { + + break; + + } else { + // 查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } } - @Override - public String toString(ConstantPool pool) { - - return super.getOperandAsMethod(pool); + if (m == null) { + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); } - - + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } } \ 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 index 073ddd73a9..5a611df6ae 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java @@ -4,26 +4,47 @@ import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.constant.StringInfo; +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.Heap; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { - public LdcCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + + ConstantInfo info = (ConstantInfo) getConstantInfo(this.getOperand()); + + String value = "TBD"; + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo) info; + value = strInfo.toString(); } - - @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; - + + return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " " + value; + + } + + public void execute(StackFrame frame, ExecutionResult result) { + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo) pool.getConstantInfo(this.getOperand()); + + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo) info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } else { + // TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); } - + + } + } \ 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 index 9c959e31dd..1345d7181f 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java @@ -1,19 +1,38 @@ 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.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.Heap; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; -public class NewObjectCmd extends TwoOperandCmd{ - - public NewObjectCmd(ClassFile clzFile, String opCode){ - super(clzFile,opCode); - } +public class NewObjectCmd extends TwoOperandCmd { - @Override - public String toString(ConstantPool pool) { - - return super.getOperandAsClassInfo(pool); - } + public NewObjectCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + + public void execute(StackFrame frame, ExecutionResult result) { + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo) this.getConstantInfo(index); + + String clzName = info.getClassName(); + + // 在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + } - } 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 index 554eac0690..c658260086 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java @@ -2,22 +2,140 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.Heap; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; -public class NoOperandCmd extends ByteCodeCommand{ +public class NoOperandCmd extends ByteCodeCommand { - public NoOperandCmd(ClassFile clzFile, String opCode) { - super(clzFile, opCode); - } + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText(); + } + + public int getLength() { + return 1; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + String opCode = this.getOpCode(); + + if (ByteCodeCommand.aload_0.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.aload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.aload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.fload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.voidreturn.equals(opCode)) { - @Override - public String toString(ConstantPool pool) { - return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if (ByteCodeCommand.ireturn.equals(opCode)) { + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.freturn.equals(opCode)) { + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); } - - - public int getLength(){ - return 1; + else if (ByteCodeCommand.astore_1.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.dup.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iconst_0.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iconst_1.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.istore_1.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.istore_2.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if (ByteCodeCommand.iadd.equals(opCode)) { + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue() + jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)) { + + frame.getOprandStack().push(null); + + } else { + throw new RuntimeException("you must forget to implement the operation :" + opCode); } + } } 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 index f3a197114c..91549d7c01 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java @@ -1,19 +1,43 @@ 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.NameAndTypeInfo; +import com.github.HarryHook.coding2017.jvm.engine.ExecutionResult; +import com.github.HarryHook.coding2017.jvm.engine.JavaObject; +import com.github.HarryHook.coding2017.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { - public PutFieldCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); - } + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } - @Override - public String toString(ConstantPool pool) { - - return super.getOperandAsField(pool); - } + @Override + public String toString() { + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo) this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo) this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } } \ 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 index 13edc86215..d0d38f368f 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java @@ -7,61 +7,62 @@ 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 abstract class TwoOperandCmd extends ByteCodeCommand { - public void setOprand1(int oprand1) { - this.oprand1 = oprand1; - } + int oprand1 = -1; + int oprand2 = -1; - public void setOprand2(int oprand2) { - this.oprand2 = oprand2; - } + public int getOprand1() { + return oprand1; + } - public int getOprand2() { - return oprand2; - } - - public TwoOperandCmd(ClassFile clzFile,String opCode) { - super(clzFile, opCode); - } + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } - 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(); - } + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } - 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; - } + 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() { + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo) getConstantInfo(index); + return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " " + info.getClassName(); + } + + protected String getOperandAsMethod() { + 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() { + 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 e4822e2bbb..3ea5bcbc53 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,8 +25,9 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override - public void accept(Visitor visitor) { - visitor.visitClassInfo(this); - } + 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 6c502016a3..cf046f6b2e 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 @@ -27,17 +27,22 @@ public ConstantPool getConstantPool() { 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); - - } - + + 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/engine/ExecutionResult.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..2e6a07838c --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutionResult.java @@ -0,0 +1,53 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import com.github.HarryHook.coding2017.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action) { + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame() { + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame() { + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd() { + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump() { + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutorEngine.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..85eeeaba50 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/ExecutorEngine.java @@ -0,0 +1,78 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.github.HarryHook.coding2017.jvm.attr.CodeAttr; +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod) { + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while (!stack.empty()) { + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if (result.isPauseAndRunNewFrame()) { + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + List paramList = nextMethod.getParameterList(); + + // 加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + List values = new ArrayList(); + + // 数据结构知识: 从栈中取出栈顶的x个元素 + while (paramNum > 0) { + values.add(currentFrame.getOprandStack().pop()); + paramNum--; + } + // 数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for (int i = values.size() - 1; i >= 0; i--) { + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/Heap.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/Heap.java new file mode 100644 index 0000000000..f249407d7f --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/Heap.java @@ -0,0 +1,43 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + + private Heap() { + } + + public static Heap getInstance() { + return instance; + } + + public JavaObject newObject(String clzName) { + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value) { + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value) { + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + + public JavaObject newInt(int value) { + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/JavaObject.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..edce5aad4f --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/JavaObject.java @@ -0,0 +1,82 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue) { + fieldValues.put(fieldName, fieldValue); + } + + public JavaObject(int type) { + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setStringValue(String value) { + stringValue = value; + } + + public String getStringValue() { + return this.stringValue; + } + + public void setIntValue(int value) { + this.intValue = value; + } + + public int getIntValue() { + return this.intValue; + } + + public int getType() { + return type; + } + + public JavaObject getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public String toString() { + switch (this.getType()) { + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className + ":" + this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default: + return null; + } + } + + public String getClassName() { + return this.className; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MethodArea.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..0e102b8765 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MethodArea.java @@ -0,0 +1,83 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.loader.ClassFileLoader; +import com.github.HarryHook.coding2017.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) { + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + public ClassFile findClassFile(String className) { + + if (map.get(className) != null) { + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + public Method getMethod(String className, String methodName, String paramAndReturnType) { + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if (m == null) { + + throw new RuntimeException("method can't be found : \n" + "class: " + className + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + public Method getMethod(MethodRefInfo methodRef) { + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if (m == null) { + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MiniJVM.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..95cc99974e --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.github.HarryHook.coding2017.jvm.loader.ClassFileLoader; + +public class MiniJVM { + + public void run(String[] classPaths, String className) throws FileNotFoundException, IOException { + + ClassFileLoader loader = new ClassFileLoader(); + for (int i = 0; i < classPaths.length; i++) { + loader.addClassPath(classPaths[i]); + } + + MethodArea methodArea = MethodArea.getInstance(); + + methodArea.setClassFileLoader(loader); + + ExecutorEngine engine = new ExecutorEngine(); + + className = className.replace(".", "/"); + + engine.execute(methodArea.getMainMethod(className)); + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/OperandStack.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/OperandStack.java new file mode 100644 index 0000000000..cd468c79f6 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/OperandStack.java @@ -0,0 +1,29 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.util.ArrayList; +import java.util.List; + +public class OperandStack { + private List operands = new ArrayList(); + + public void push(JavaObject jo) { + operands.add(jo); + } + + public JavaObject pop() { + int index = size() - 1; + JavaObject jo = (JavaObject) operands.get(index); + operands.remove(index); + return jo; + + } + + public JavaObject top() { + int index = size() - 1; + return (JavaObject) operands.get(index); + } + + public int size() { + return operands.size(); + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/StackFrame.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..8ceee230dd --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/engine/StackFrame.java @@ -0,0 +1,116 @@ +package com.github.HarryHook.coding2017.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.method.Method; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m) { + + StackFrame frame = new StackFrame(m); + + return frame; + } + + private StackFrame(Method m) { + this.m = m; + + } + + public JavaObject getLocalVariableValue(int index) { + return this.localVariableTable.get(index); + } + + public Stack getOprandStack() { + return this.oprandStack; + } + + public int getNextCommandIndex(int offset) { + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for (int i = 0; i < cmds.length; i++) { + if (cmds[i].getOffset() == offset) { + return i; + } + } + throw new RuntimeException("Can't find next command"); + } + + public ExecutionResult execute() { + + ByteCodeCommand[] cmds = m.getCmds(); + + while (index < cmds.length) { + + ExecutionResult result = new ExecutionResult(); + // 缺省值是执行下一条命令 + result.setNextAction(ExecutionResult.RUN_NEXT_CMD); + + System.out.println(cmds[index].toString()); + + cmds[index].execute(this, result); + + if (result.isRunNextCmd()) { + index++; + } else if (result.isExitCurrentFrame()) { + return result; + } else if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } else if (result.isJump()) { + int offset = result.getNextCmdOffset(); + this.index = getNextCommandIndex(offset); + } else { + index++; + } + + } + + // 当前StackFrmae的指令全部执行完毕,可以退出了 + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + + } + + public void setLocalVariableTable(List values) { + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo) { + // 问题: 为什么要这么做?? + if (this.localVariableTable.size() - 1 < index) { + for (int i = this.localVariableTable.size(); i <= index; i++) { + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + } + + public Method getMethod() { + return m; + } + +} 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 08b8ff029b..344177f549 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 @@ -4,6 +4,9 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import java.util.ArrayList; +import java.util.List; + import javax.management.RuntimeErrorException; import com.github.HarryHook.coding2017.jvm.attr.AttributeInfo; @@ -54,26 +57,28 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { int nameIndex = iter.nextU2ToInt(); int descriptorIndex = iter.nextU2ToInt(); int attributeCount = iter.nextU2ToInt(); - + Method m = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); - - for(int i=1; i<=attributeCount; i++) { + + for (int i = 1; i <= attributeCount; i++) { int attrNameIndex = iter.nextU2ToInt(); String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); iter.back(2); - - if(AttributeInfo.CODE.equalsIgnoreCase(attrName)) { + + if (AttributeInfo.CODE.equalsIgnoreCase(attrName)) { CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); m.setCodeAttr(codeAttr); } else { throw new RuntimeException("only Attribute is complemented!"); } - + } return m; } - public String toString(ConstantPool pool) { + + public String toString() { + ConstantPool pool = this.clzFile.getConstantPool(); StringBuffer buffer = new StringBuffer(); String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); @@ -81,7 +86,66 @@ public String toString(ConstantPool pool) { buffer.append(this.codeAttr.toString(pool)); return buffer.toString(); } - public ByteCodeCommand[] getCmds() { + + public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); -} + } + + private String getParamAndReturnType() { + UTF8Info nameAndTypeInfo = (UTF8Info) this.getClzFile().getConstantPool() + .getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList() { + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first + 1, last); + + List paramList = new ArrayList(); + + if ((null == param) || "".equals(param)) { + return paramList; + } + + while (!param.equals("")) { + + int pos = 0; + // 这是一个对象类型 + if (param.charAt(pos) == 'L') { + + int end = param.indexOf(";"); + + if (end == -1) { + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos + 1, end)); + + pos = end + 1; + + } else if (param.charAt(pos) == 'I') { + // int + paramList.add("I"); + pos++; + + } else if (param.charAt(pos) == 'F') { + // float + paramList.add("F"); + pos++; + + } else { + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/MiniJVMTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..d30ddd7c26 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/MiniJVMTest.java @@ -0,0 +1,29 @@ +package com.github.HarryHook.coding2017.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.HarryHook.coding2017.jvm.engine.MiniJVM;; + +public class MiniJVMTest { + + static final String PATH = "F:\\Coding2017\\group02\\727171008\\bin"; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception { + String[] classPaths = { PATH }; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.github.HarryHook.coding2017.jvm.test.EmployeeV1"); + + } + +} \ No newline at end of file From 11319cbd905db9f8be7680b719e3f53f9ba54ec1 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 3 May 2017 22:03:01 +0800 Subject: [PATCH 149/151] update stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加stack作业 : QuickMinstack , StackWithTwoQueues, TwoStackInOneArray --- .../coding2017/stack/QuickMinStack.java | 22 +++++++ .../coding2017/stack/StackWithTwoQueues.java | 13 ++++ .../coding2017/stack/TwoStackInOneArray.java | 66 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java create mode 100644 group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java new file mode 100644 index 0000000000..2faae41b04 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java @@ -0,0 +1,22 @@ +package com.github.HarryHook.coding2017.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * + * @author liuxin + * + */ +public class QuickMinStack { + public void push(int data) { + + } + + public int pop() { + return -1; + } + + public int findMin() { + return -1; + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..ca649296f7 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java @@ -0,0 +1,13 @@ +package com.github.HarryHook.coding2017.stack; + +public class StackWithTwoQueues { + + public void push(int data) { + + } + + public int pop() { + return -1; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..ed0f68ceb4 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java @@ -0,0 +1,66 @@ +package com.github.HarryHook.coding2017.stack; + +/** + * 用一个数组实现两个栈 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return null; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + return null; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + return null; + } + +} From 1c9a48a9c52d3923b995b0a6d833e93a1f52113a Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 4 May 2017 17:39:29 +0800 Subject: [PATCH 150/151] update stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现QuickMinStack, StackWithTwoQueue, TwoStackInOneArray --- .../coding2017/stack/QuickMinStack.java | 50 +++++++++- .../coding2017/stack/StackWithTwoQueues.java | 49 +++++++++- .../coding2017/stack/TwoStackInOneArray.java | 94 ++++++++++++++++++- 3 files changed, 184 insertions(+), 9 deletions(-) diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java index 2faae41b04..af6bb37e2b 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java @@ -1,5 +1,11 @@ package com.github.HarryHook.coding2017.stack; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.sun.xml.internal.ws.encoding.SwACodec; + /** * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 @@ -8,15 +14,55 @@ * */ public class QuickMinStack { + Stack s1 = new Stack<>(); + Stack s2 = new Stack<>(); + public void push(int data) { + s1.push(data); + + if (s2.isEmpty()) { + s2.push(data); + } else if (data > s2.peek()) { + s2.push(s2.peek()); + } else { + s2.push(data); + } + } public int pop() { - return -1; + if (s1.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + s2.pop(); + return s1.pop(); } public int findMin() { - return -1; + if (s2.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + return s2.peek(); + } + + public static void main(String[] args) { + QuickMinStack stack = new QuickMinStack(); + stack.push(5); + stack.push(3); + stack.push(2); + stack.push(4); + stack.push(1); + System.out.println("findMin: " + stack.findMin()); + System.out.println("pop: " + stack.pop()); + System.out.println("findMin: " + stack.findMin()); + System.out.println("pop: " + stack.pop()); + System.out.println("findMin: " + stack.findMin()); + System.out.println("pop: " + stack.pop()); + System.out.println("findMin: " + stack.findMin()); + System.out.println("pop: " + stack.pop()); + System.out.println("findMin: " + stack.findMin()); + System.out.println("pop: " + stack.pop()); + System.out.println("findMin: " + stack.findMin()); } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java index ca649296f7..14e109e53e 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/StackWithTwoQueues.java @@ -1,13 +1,58 @@ package com.github.HarryHook.coding2017.stack; +import com.github.HarryHook.coding2017.queue.Queue; + public class StackWithTwoQueues { + private Queue queue1; + private Queue queue2; - public void push(int data) { + public StackWithTwoQueues() { + queue1 = new Queue<>(); // 入栈 + queue2 = new Queue<>(); // 出栈 + } + + public boolean isEmpty() { + if (queue1.isEmpty() && queue2.isEmpty()) { + return true; + } + return false; + } + public int size() { + return queue1.size() + queue2.size(); + } + + public void push(int data) { + queue1.enQueue(data); } public int pop() { - return -1; + if (isEmpty()) { + throw new RuntimeException("stack is empty"); + } + while(!(queue1.isEmpty())) { + queue2.enQueue(queue1.deQueue()); + } + int tmp = 0; + while(!(queue2.isEmpty())) { + tmp = queue2.deQueue(); + if(queue2.isEmpty()) { + break; + } + queue1.enQueue(tmp); + } + return tmp; + } + public static void main(String[] args) { + StackWithTwoQueues stack = new StackWithTwoQueues(); + stack.push(1); + stack.push(2); + stack.push(3); + System.out.println(stack.pop()); + stack.push(43); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java index ed0f68ceb4..d8af1f8483 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java @@ -1,5 +1,7 @@ package com.github.HarryHook.coding2017.stack; +import java.util.Arrays; + /** * 用一个数组实现两个栈 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 * @@ -7,7 +9,9 @@ * */ public class TwoStackInOneArray { - Object[] data = new Object[10]; + Object[] data = new Object[6]; + int i = 0; + int j = data.length - 1; /** * 向第一个栈中压入元素 @@ -15,6 +19,10 @@ public class TwoStackInOneArray { * @param o */ public void push1(Object o) { + if (i > j) { + expansion(); + } + data[i++] = o; } @@ -24,7 +32,12 @@ public void push1(Object o) { * @return */ public Object pop1() { - return null; + if (data[0] == null) { + throw new RuntimeException("stack1 is empty"); + } + Object tmp = data[i - 1]; + data[--i] = null; + return tmp; } /** @@ -34,13 +47,17 @@ public Object pop1() { */ public Object peek1() { - return null; + return data[i - 1]; } /* * 向第二个栈压入元素 */ public void push2(Object o) { + if (i > j) { + expansion(); + } + data[j--] = o; } @@ -50,7 +67,13 @@ public void push2(Object o) { * @return */ public Object pop2() { - return null; + if (data[data.length - 1] == null) { + throw new RuntimeException("stack2 is empty"); + } + Object tmp = data[j + 1]; + data[++j] = null; + return tmp; + } /** @@ -60,7 +83,68 @@ public Object pop2() { */ public Object peek2() { - return null; + return data[j + 1]; + } + + // 给数组扩容 + public void expansion() { + int oldCapacity = data.length; + int newCapacity = oldCapacity * 2; // 此时扩容是因为数组有可能全是stack2的元素 + data = Arrays.copyOf(data, newCapacity); + int newIndex = newCapacity - 1; + for (int k = oldCapacity - 1; k > j; k--) { + data[newIndex--] = data[k]; + data[k] = null; + } + j += newCapacity - oldCapacity; + } + + public static void main(String[] args) { + TwoStackInOneArray stack = new TwoStackInOneArray(); + + stack.push1(3); + stack.push1(5); + stack.push1(6); + stack.push1(11); + System.out.println("peek1: " + stack.peek1()); + System.out.println("pop1: " + stack.pop1()); + System.out.println("pop1: " + stack.pop1()); + stack.push1(61); + System.out.println("pop1: " + stack.pop1()); + System.out.println("pop1: " + stack.pop1()); + System.out.println("peek1: " + stack.peek1()); + System.out.println("pop1: " + stack.pop1()); + + stack.push2(123); + stack.push2(1); + stack.push2(4); + + stack.push1(3); + stack.push1(5); + stack.push1(6); + + stack.push2(123); + stack.push2(1); + stack.push2(4); + stack.push2(12); + stack.push2(2); + stack.push2(8); + System.out.println("pop1: " + stack.pop1()); + System.out.println("peek1: " + stack.peek1()); + System.out.println("pop1: " + stack.pop1()); + System.out.println("pop1: " + stack.pop1()); + + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + System.out.println("pop2: " + stack.pop2()); + } } From 3f0d7a926ef209bd21cd7d61f395f26b53c41efe Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 4 May 2017 17:45:57 +0800 Subject: [PATCH 151/151] update stack --- .../github/HarryHook/coding2017/stack/QuickMinStack.java | 6 +----- .../HarryHook/coding2017/stack/TwoStackInOneArray.java | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java index af6bb37e2b..70f1d03903 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/QuickMinStack.java @@ -1,16 +1,12 @@ package com.github.HarryHook.coding2017.stack; -import java.util.ArrayList; -import java.util.List; import java.util.Stack; -import com.sun.xml.internal.ws.encoding.SwACodec; - /** * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 * - * @author liuxin + * @author HarryHook * */ public class QuickMinStack { diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java index d8af1f8483..0829b5b34c 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/TwoStackInOneArray.java @@ -5,7 +5,7 @@ /** * 用一个数组实现两个栈 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 * - * @author liuxin + * @author HarryHook * */ public class TwoStackInOneArray {