Skip to content

Commit

Permalink
字段与attr的代码初步
Browse files Browse the repository at this point in the history
  • Loading branch information
miniyk2012 committed Apr 17, 2017
1 parent c0e03cd commit 4f3cecb
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,7 +17,8 @@ public class ClassFile {
private AccessFlag accessFlag;
private ClassIndex clzIndex;
private ConstantPool pool;

private List<Field> fields = new ArrayList<Field>();
private List<Method> methods = new ArrayList<Method>();

public ClassIndex getClzIndex() {
return clzIndex;
Expand All @@ -24,8 +30,6 @@ public void setAccessFlag(AccessFlag accessFlag) {
this.accessFlag = accessFlag;
}



public ConstantPool getConstantPool() {
return pool;
}
Expand All @@ -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<Field> getFields(){
return this.fields;
}
public void addMethod(Method m){
this.methods.add(m);
}
public List<Method> 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());

}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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 ;

}
}
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down Expand Up @@ -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<Field> 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<Method> methods = clzFile.getMethods();
ConstantPool pool = clzFile.getConstantPool();

{
Method m = methods.get(0);
assertMethodEquals(pool,m,
"<init>",
"(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);
}

}

0 comments on commit 4f3cecb

Please sign in to comment.