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(); + } }