From 4f3cecbd63b2fa0ee5a8f3d9e10c6b7163f840c5 Mon Sep 17 00:00:00 2001 From: thomas_young Date: Tue, 18 Apr 2017 06:13:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=B8=8Eattr=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/stack/expr/InfixExprTest.java | 4 + .../coderising/jvm/clz/ClassFile.java | 26 +++-- .../coderising/jvm/field/Field.java | 50 ++++++++++ .../coderising/jvm/method/Method.java | 96 +++++++++++++++++++ .../jvm/test/ClassFileloaderTest.java | 77 ++++++++++++++- 5 files changed, 245 insertions(+), 8 deletions(-) create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java create mode 100644 group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java index 706aaea86e..a14953535d 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java @@ -46,6 +46,10 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } + { + InfixExpr expr = new InfixExpr("10-30+50-20/10/2*4"); + Assert.assertEquals(26, expr.evaluate(), 0.001f); + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java index c4d13704f2..82eee82fb5 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/clz/ClassFile.java @@ -1,9 +1,14 @@ package com.github.miniyk2012.coding2017.coderising.jvm.clz; +import assignments.jvm.field.Field; +import assignments.jvm.method.Method; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ClassInfo; import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import java.util.ArrayList; +import java.util.List; + public class ClassFile { private int minorVersion; @@ -12,7 +17,8 @@ public class ClassFile { private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; - + private List fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -24,8 +30,6 @@ public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - public ConstantPool getConstantPool() { return pool; } @@ -43,20 +47,28 @@ public void setMajorVersion(int majorVersion) { } public void setConstPool(ConstantPool pool) { this.pool = pool; - + } + public void addField(Field f){ + this.fields.add(f); + } + public List getFields(){ + return this.fields; + } + public void addMethod(Method m){ + this.methods.add(m); + } + public List getMethods() { + return methods; } public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - public void print(){ - if(this.accessFlag.isPublicClass()){ System.out.println("Access flag : public "); } System.out.println("Class Name:"+ getClassName()); - System.out.println("Super Class Name:"+ getSuperClassName()); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..017e6cd8bc --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.field; + +import assignments.jvm.constant.ConstantPool; +import assignments.jvm.constant.UTF8Info; +import assignments.jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + + private ConstantPool pool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..f9e62fbb93 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/method/Method.java @@ -0,0 +1,96 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.method; + +import assignments.jvm.clz.ClassFile; +import assignments.jvm.attr.AttributeInfo; +import assignments.jvm.attr.CodeAttr; +import assignments.jvm.constant.ConstantPool; +import assignments.jvm.constant.UTF8Info; +import assignments.jvm.loader.ByteCodeIterator; + + + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + + + +public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for( int j=1; j<= attribCount; j++){ + + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else{ + throw new RuntimeException("only CODE attribute is implemented , please implement the "+ attrName); + } + + } + + return m ; + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java index 013ec8073a..21d5ddbd71 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java @@ -1,15 +1,19 @@ package com.github.miniyk2012.coding2017.coderising.jvm.test; +import assignments.jvm.field.Field; +import assignments.jvm.method.Method; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex; import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; import com.github.miniyk2012.coding2017.coderising.jvm.loader.ClassFileLoader; import com.github.miniyk2012.coding2017.coderising.jvm.util.Util; import org.junit.After; -import org.junit.Assert; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.List; + public class ClassFileloaderTest { @@ -172,5 +176,76 @@ public void testClassIndex(){ Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } + /** + * 下面是第三次JVM课应实现的测试用例 + */ + @Test + public void testReadFields(){ + + List fields = clzFile.getFields(); + Assert.assertEquals(2, fields.size()); + { + Field f = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ + String methodName = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + String code = m.getCodeAttr().getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } }