diff --git a/.gitignore b/.gitignore index 156b10d1f1..6988a7c6d8 100644 --- a/.gitignore +++ b/.gitignore @@ -215,7 +215,7 @@ pip-log.txt #Mr Developer .mr.developer.cfg -.gitignore +#.gitignore ======= @@ -235,7 +235,7 @@ hs_err_pid* .recommenders -*.xml +#*.xml *.iml .idea *.iml @@ -248,7 +248,7 @@ rebel-remote.xml .metadata target -*.class +#*.class log *.log @@ -257,7 +257,7 @@ tmp .metadata RemoteSystemsTempFiles -.gitignore +#.gitignore .recommenders .idea/ diff --git a/group24/75939388/.gitignore b/group24/75939388/.gitignore new file mode 100644 index 0000000000..596bd7346d --- /dev/null +++ b/group24/75939388/.gitignore @@ -0,0 +1,4 @@ +*.class +target/ +*.iml +.idea/ \ No newline at end of file diff --git a/group24/75939388/learning2017/pom.xml b/group24/75939388/learning2017/pom.xml new file mode 100644 index 0000000000..ebdd03610c --- /dev/null +++ b/group24/75939388/learning2017/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + tee.w + learning2017 + 1.0 + learning2017 + pom + + https://github.com/macvis/coding2017 + 码农翻身 + + + + TerrenceWen + https://github.com/macvis/ + macvis@126.com + + + + + + + aliyun + aliyun + http://maven.aliyun.com/nexus/content/groups/public + + true + never + + + false + + + + + + + aliyun + aliyun + http://maven.aliyun.com/nexus/content/groups/public + + true + + + false + + + + + + + + + junit + junit + 4.12 + + + + + dom4j + dom4j + 1.6.1 + + + + + jaxen + jaxen + 1.1.6 + + + + + commons-io + commons-io + 2.5 + + + org.apache.commons + commons-lang3 + 3.5 + + + commons-codec + commons-codec + 1.10 + + + org.apache.commons + commons-collections4 + 4.1 + + + + \ No newline at end of file diff --git a/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1 verbose.txt b/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1 verbose.txt new file mode 100644 index 0000000000..b161a0cd6e --- /dev/null +++ b/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1 verbose.txt @@ -0,0 +1,164 @@ +youchaowendeMacBook-Pro:Downloads Tee$ javap -verbose EmployeeV1.class +Classfile /Users/Tee/Downloads/EmployeeV1.class + Last modified 2017-4-27; 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" +youchaowendeMacBook-Pro:Downloads Tee$ \ No newline at end of file diff --git a/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1.class b/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1.class new file mode 100644 index 0000000000..c6c3c4a415 Binary files /dev/null and b/group24/75939388/learning2017/resources/classes/miniJVM/EmployeeV1.class differ diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java similarity index 97% rename from group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java rename to group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java index 8ae862da33..246641cb4a 100644 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java @@ -1,4 +1,6 @@ -package basic.dataStructure; +package basic.dataStructure.array; + +import basic.dataStructure.List; /** * Created by macvi on 2017/4/2. diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LRUPageFrame.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LRUPageFrame.java new file mode 100644 index 0000000000..8746fc44a0 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LRUPageFrame.java @@ -0,0 +1,163 @@ +package basic.dataStructure.linkedList; + +/** + * @author : 温友朝 + */ +public class LRUPageFrame { + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() {} + + Node(Node prev, Node next, int pageNum){ + this.prev = prev; + this.next = next; + this.pageNum = pageNum; + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + * + * @param pageNum + */ + public void access(int pageNum){ + if(first == null){ + last = first = new Node(null, null, pageNum); + this.currentSize++; + return; + } + + if(first.pageNum == pageNum){ + return; + } + + if(currentSize < capacity){ + addToFirst(pageNum); + this.currentSize ++; + }else{ + //遍历 + boolean flag = false; + for(int i = 0; i < capacity; i++){ + if(get(i) == pageNum){ + flag = true; + break; + } + } + + //有相同的,交换该数据至栈顶 + if(flag){ + this.moveToFirst(pageNum); + }else{ + //没有相同的,移除栈底元素 + removeLast(); + //添加 + addToFirst(pageNum); + } + } + } + + /** + * 新增至栈底 + * @param pageNum + */ + private void addToLast(int pageNum){ + Node node = new Node(last, null, pageNum); + last.next = node; + this.last = node; + this.currentSize++; + } + + /** + * 新增值栈顶 + * @param pageNum + */ + private void addToFirst(int pageNum){ + Node node = new Node(null, first, pageNum); + first.prev = node; + this.first = node; + this.currentSize++; + } + + /** + * 移除栈底的元素 + */ + public void removeLast(){ + Node node = last.prev; + node.next = null; + this.last = node; + this.currentSize--; + } + + /** + * 从栈底数起,取数 + */ + public int get(int index){ + int in = 0; + Node temp = last; + int res = -1; + while (temp != null){ + if(index == in){ + res = temp.pageNum; + } + in++; + temp = temp.prev; + } + + return res; + } + + public void moveToFirst(int pageNum){ + Node temp = last; + while (temp != null){ + if(temp.pageNum == pageNum){ + break; + } + temp = temp.prev; + } + + //处理节点,任意位置时重组链接 + if(temp.next != null){ + temp.prev.next = temp.next; + temp.next.prev = temp.prev; + }else{ + //栈底remove调 + removeLast(); + } + + addToFirst(pageNum); + } + + public int size(){ + return this.currentSize; + } + + 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/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LinkedList.java similarity index 97% rename from group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java rename to group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LinkedList.java index 3ac85ad37b..aa19b4cef5 100644 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LinkedList.java @@ -1,4 +1,8 @@ -package basic.dataStructure; +package basic.dataStructure.linkedList; + +import basic.dataStructure.ArrayUtil; +import basic.dataStructure.List; +import basic.dataStructure.array.ArrayList; /** * Created by macvi on 2017/4/3. @@ -169,7 +173,7 @@ public void reverse(){ /** * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 例如:array = 2->5->7->8 , 删除以后的值为 7->8 * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 */ diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java similarity index 97% rename from group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java rename to group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java index 36ca7e9647..5096f9297c 100644 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java @@ -1,4 +1,4 @@ -package basic.dataStructure; +package basic.dataStructure.queue; /** * Created by macvi on 2017/4/4. diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java similarity index 60% rename from group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java rename to group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java index bea16033fa..ea83d96e2b 100644 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java @@ -1,4 +1,6 @@ -package basic.dataStructure; +package basic.dataStructure.stack; + +import basic.dataStructure.array.ArrayList; /** * Created by macvi on 2017/4/4. @@ -7,6 +9,14 @@ public class Stack { private ArrayList elementData = new ArrayList(); + public Stack(){} + + public Stack(Object...objs){ + for(int i = 0; i < objs.length; i++){ + this.push(objs[i]); + } + } + public void push(Object o){ this.elementData.add(o); } @@ -20,7 +30,7 @@ public Object pop(){ public Object peek(){ int index = elementData.size() - 1; - return elementData.get(index); + return index == -1 ? null : elementData.get(index); } public boolean isEmpty(){ return peek() == null; @@ -33,7 +43,11 @@ public int size(){ public String toString() { StringBuffer sb = new StringBuffer(); for(int i = this.size() - 1; i >= 0; i--){ - sb.append(elementData.get(i).toString()).append(","); + if(i != 0){ + sb.append(elementData.get(i).toString()).append(","); + }else{ + sb.append(elementData.get(i).toString()); + } } return sb.toString(); diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/StackUtil.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/StackUtil.java new file mode 100644 index 0000000000..1d55a2d47e --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/StackUtil.java @@ -0,0 +1,105 @@ +package basic.dataStructure.stack; + +public class StackUtil { + + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static Stack reverse(Stack s) { + Stack st = new Stack(); + int size = s.size(); + for(int i = 0; i < size; i++){ + st.push(s.pop()); + } + return st; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static Stack remove(Stack s,Object o) { + Stack tmp = new Stack(); + int size = s.size(); + for(int i = 0; i < size; i++){ + Object obj = s.peek(); + if(obj != o && !obj.equals(o)){ + tmp.push(s.pop()); + }else{ + s.pop(); + } + } + return tmp; + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + Stack temp = new Stack(); + int size = s.size(); + Object[] objs = new Object[len]; + for(int i = 0; i < size; i++){ + Object obj = s.pop(); + if(i < len){ + objs[i] = obj; + } + temp.push(obj); + } + + for(int i = 0 ; i < size; i ++){ + s.push(temp.pop()); + } + + return objs; + } + /** + * 字符串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 bracket = new Stack(")", "("); + + //方括号 + Stack brackets = new Stack("]", "["); + + //花括号 + Stack braces = new Stack("}", "{"); + + char[] symArr = s.toCharArray(); + int length = symArr.length; + for(int i = 0; i < length/2; i++){ + String sym = String.valueOf(symArr[i]); + String endSym = String.valueOf(symArr[length - i -1]); + if(sym.equals(bracket.peek())){ + bracket = remove(bracket, sym); + bracket = remove(bracket, endSym); + } + + if(sym.equals(brackets.peek())){ + brackets = remove(brackets, sym); + brackets = remove(brackets, endSym); + } + + if(sym.equals(braces.peek())){ + braces = remove(braces, sym); + braces = remove(braces, endSym); + } + } + return bracket.isEmpty() && brackets.isEmpty() && braces.isEmpty(); + } + + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Calculator.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Calculator.java new file mode 100644 index 0000000000..fe6510b532 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Calculator.java @@ -0,0 +1,23 @@ +package basic.dataStructure.stack.expr; + +/** + * @author : 温友朝 + * @date : 2017/4/27 + */ +public class Calculator { + public static float getFloat(float val1, float val2, String oper) { + float res = 0l; + if (oper.equals("*")) { + res = val1 * val2; + } else if (oper.equals("+")) { + res = val1 + val2; + } else if (oper.equals("-")) { + res = val1 - val2; + } else { + if (val2 == 0) throw new RuntimeException("cannot divide 0, calculation canceled"); + res = val1 / val2; + } +// System.out.println("计算结果: " + val1 + oper + val2 + "=" + res); + return res; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixExpr.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..c31fe35737 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixExpr.java @@ -0,0 +1,65 @@ +package basic.dataStructure.stack.expr; + +import basic.dataStructure.stack.Stack; + +import java.util.List; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List tokens = TokenParser.parse(expr); + Stack numbers = new Stack(); + Stack operators = new Stack(); + + int temp = 0; + + for (Token token : tokens) { + if (token.isOperator()) { + operators.push(token); + } + + if (token.isNumber()) { + numbers.push(token); + } + + //先计算 + int opeSize = operators.size(); + int numSize = numbers.size(); + + float val1 = ((Token) numbers.pop()).getFloatValue(); + float val2 = ((Token) numbers.pop()).getFloatValue(); + if (numSize == 3 && opeSize == 2) { + Token tmp = (Token) operators.pop(); + if (tmp.hasHigherPriority((Token) operators.peek())) { + //如果1+2*3,先计算numbers后两位 + numbers.push(new Token(Token.NUMBER, Calculator.getFloat(val1, val2, tmp.toString()) + "")); + } else { + //如果1*2+3,先计算numbers栈前两位 + //先保存数字和运算符 + Token sNum = (Token) numbers.pop(); + Token sOper = tmp; + + //需要进行计算的运算符 + Token oper = (Token) operators.pop(); + numbers.push(new Token(Token.NUMBER, Calculator.getFloat(val1, val2, oper.toString()) + "")); + numbers.push(new Token(Token.NUMBER, sNum + "")); + operators.push(new Token(Token.OPERATOR, sOper.toString())); + } + } + } + + if (numbers.size() == 2 && operators.size() == 1) { + float val1 = ((Token) numbers.pop()).getFloatValue(); + float val2 = ((Token) numbers.pop()).getFloatValue(); + return Calculator.getFloat(val1, val2, (operators.pop()).toString()); + } else { + throw new RuntimeException("last calculation exception, numbers.size=" + numbers.size() + ", operators.size=" + operators.size()); + } + } + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixToPostfix.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..b5b9552013 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixToPostfix.java @@ -0,0 +1,73 @@ +package basic.dataStructure.stack.expr; + +import basic.dataStructure.stack.Stack; + +import java.util.ArrayList; +import java.util.List; + +/** + * 中序转后序 + */ +public class InfixToPostfix { + + public static List convert(String expr) { + List postfixTokenList = new ArrayList(); + + List original = TokenParser.parse(expr); + Stack buffer = new Stack(); + for(Token t : original){ + //数字直接放入结果 + if(t.isNumber()) postfixTokenList.add(t); + + //左括号,放入缓存 + if(t.isLBracket()) buffer.push(t); + + //右括号, 遍历完成后不用放入结果集 + if(t.isRBracket()){ + if(buffer.size() == 0){ + throw new RuntimeException("brackets are not in pair, check your expression"); + }else{ + //遍历直至左括号 + Token tmp = (Token) buffer.peek(); + while (!tmp.isLBracket()){ + if(buffer.size() == 1 && !tmp.isLBracket()) throw new RuntimeException("brackets are not in pair, check your expression"); + //放入结果list + postfixTokenList.add((Token) buffer.pop()); + tmp = (Token)buffer.peek(); + } + } + } + + //处理运算符,若缓存栈顶的运算符优先级高于或等于该运算符时,则进行遍历: + //缓存中找出的运算符直接入结果list,遍历完成后当前运算符压进缓存栈中 + if(t.isOperator()){ + Token tmp = (Token) buffer.peek(); + while(tmp != null && tmp.isOperator() && tmp.hasHigherPriority(t)){ + //弹出至结果list + postfixTokenList.add((Token) buffer.pop()); + tmp = (Token) buffer.peek(); + } + buffer.push(t); + } + } + + //遍历完成后,若缓存还有值,则直接放到结果集,并去掉左括号 + while (buffer.size() > 0){ + Token t = (Token) buffer.pop(); + if(!t.isBracket()){ + postfixTokenList.add(t); + } + } + + return postfixTokenList; + } + + + public static void main(String[] args) { +// convert("9+(3-1)*3+10/2"); + List list = convert("1+(2+3*4-5)/2+10-1"); + System.out.println(list.toString()); +// convert("2+3*4-5"); + } + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PostfixExpr.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..cfbd67c5bf --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PostfixExpr.java @@ -0,0 +1,43 @@ +package basic.dataStructure.stack.expr; + +import basic.dataStructure.stack.Stack; + +import java.util.List; + +/** + * 后序表达式 + */ +public class PostfixExpr { + String expr = null; + + /** + * 23*21-/341-*+ + */ + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List tokens = TokenParser.parse(expr); + + Stack numbers = new Stack(); + Stack opers = new Stack(); + + for(Token t : tokens){ + if(t.isNumber()) numbers.push(t); + if(t.isOperator()) opers.push(t); + + if(opers.size() == 1){ + float num1 = ((Token)numbers.pop()).getFloatValue(); + float num2 = ((Token)numbers.pop()).getFloatValue(); + String oper = (opers.pop()).toString(); + float res = Calculator.getFloat(num1, num2, oper); + numbers.push(new Token(Token.NUMBER, res + "")); + } + } + + return ((Token) numbers.pop()).getFloatValue(); + } + + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PrefixExpr.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..0f85c42f47 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/PrefixExpr.java @@ -0,0 +1,22 @@ +package basic.dataStructure.stack.expr; + +import org.apache.commons.lang3.StringUtils; + +/** + * 前序表达式 + */ +public class PrefixExpr { + String expr = null; + + /** + * +/*23-21*3-41 + * @param expr + */ + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return new PostfixExpr(StringUtils.reverse(expr)).evaluate(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Token.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Token.java new file mode 100644 index 0000000000..0c105d76a4 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/Token.java @@ -0,0 +1,69 @@ +package basic.dataStructure.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 OPERATOR = 1; + static final int NUMBER = 2; + static final int LBRACKET = -1; + static final int RBRACKET = -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 boolean isLBracket(){ + return type == LBRACKET; + } + + public boolean isRBracket(){ + return type == RBRACKET; + } + + public boolean isBracket(){ + return type == LBRACKET || type == RBRACKET; + } + + public int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + public float getFloatValue(){ + return Float.valueOf(value).floatValue(); + } + + 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/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/TokenParser.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/TokenParser.java new file mode 100644 index 0000000000..0f3169c27e --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/TokenParser.java @@ -0,0 +1,74 @@ +package basic.dataStructure.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 if (isLeftBracket(String.valueOf(c))) { + Token t = new Token(Token.LBRACKET, String.valueOf(c)); + tokens.add(t); + i++; + } else if (isRightBracket(String.valueOf(c))) { + Token t = new Token(Token.RBRACKET, String.valueOf(c)); + tokens.add(t); + i++; + } 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); + } + + private static boolean isLeftBracket(String s) { + return s.equals("("); + } + + private static boolean isRightBracket(String s) { + return s.equals(")"); + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java b/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java deleted file mode 100644 index 565983ab06..0000000000 --- a/group24/75939388/learning2017/src/main/java/miniJVM/Demo.java +++ /dev/null @@ -1,7 +0,0 @@ -package miniJVM; - -/** - * Created by macvi on 2017/4/11. - */ -public class Demo { -} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/attr/AttributeInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/attr/AttributeInfo.java new file mode 100644 index 0000000000..a35c1bc7e1 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/attr/CodeAttr.java b/group24/75939388/learning2017/src/main/java/miniJVM/attr/CodeAttr.java new file mode 100644 index 0000000000..9c6147cdb4 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/attr/CodeAttr.java @@ -0,0 +1,71 @@ +package miniJVM.attr; + +import miniJVM.clz.ClassFile; +import miniJVM.cmd.ByteCodeCommand; +import miniJVM.cmd.CommandParser; +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 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.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLength = iter.nextU4ToInt(); + String cmdCodes = iter.nextUxToHexString(codeLength); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, cmdCodes); + + return new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, cmdCodes, cmds); + } + + 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 LineNumberItem(int startPC, int lineNum){ + this.startPC = startPC; + this.lineNum = 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.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + int lineNumberTableLength = iter.nextU2ToInt(); + LineNumberTable table = new LineNumberTable(attributeNameIndex, attributeLength); + for(int i = 0; i < lineNumberTableLength; i ++){ + int startPC = iter.nextU2ToInt(); + int lineNum = iter.nextU2ToInt(); + LineNumberItem item = new LineNumberItem(startPC, lineNum); + 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/group24/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableItem.java b/group24/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableItem.java new file mode 100644 index 0000000000..7a2794dee7 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableTable.java b/group24/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableTable.java new file mode 100644 index 0000000000..0b46d90c3d --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/attr/LocalVariableTable.java @@ -0,0 +1,55 @@ +package miniJVM.attr; + + +import miniJVM.constant.ConstantPool; +import miniJVM.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 attributeNameIndex = iter.nextU2ToInt(); + int attributeLength = iter.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(attributeNameIndex, attributeLength); + int localVariableTableLength = iter.nextU2ToInt(); + for(int i = 0; i < localVariableTableLength; i++){ + int startPC = iter.nextU2ToInt(); + int length = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int index = iter.nextU2ToInt(); + LocalVariableItem item = new LocalVariableItem(); + 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/group24/75939388/learning2017/src/main/java/miniJVM/attr/StackMapTable.java b/group24/75939388/learning2017/src/main/java/miniJVM/attr/StackMapTable.java new file mode 100644 index 0000000000..ffe45f2a73 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package miniJVM.attr; + + +import miniJVM.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/75939388/learning2017/src/main/java/miniJVM/clz/AccessFlag.java b/group24/75939388/learning2017/src/main/java/miniJVM/clz/AccessFlag.java new file mode 100644 index 0000000000..72ac22ec3b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/clz/ClassFile.java b/group24/75939388/learning2017/src/main/java/miniJVM/clz/ClassFile.java new file mode 100644 index 0000000000..7e723f4a24 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/clz/ClassFile.java @@ -0,0 +1,107 @@ +package miniJVM.clz; + + +import miniJVM.constant.ClassInfo; +import miniJVM.constant.ConstantPool; +import miniJVM.field.Field; +import miniJVM.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 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 me : methods){ + String meName = pool.getUTF8String(me.getNameIndex()); + String meParamReturnType = pool.getUTF8String(me.getDescriptorIndex()); + if (meName.equals(methodName) && meParamReturnType.equals(paramAndReturnType)){ + return me; + } + } + throw new RuntimeException("methodName = " + methodName + " and paramAndReturnType=" + paramAndReturnType + "'s method not found"); + } + public Method getMainMethod(){ + return getMethod("main", "([Ljava/lang/String;)V"); + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/clz/ClassIndex.java b/group24/75939388/learning2017/src/main/java/miniJVM/clz/ClassIndex.java new file mode 100644 index 0000000000..5c406c3e66 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/clz/ClassIndex.java @@ -0,0 +1,24 @@ +package miniJVM.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public ClassIndex(int thisClassIndex, int superClassIndex){ + this.thisClassIndex = thisClassIndex; + this.superClassIndex = 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/75939388/learning2017/src/main/java/miniJVM/cmd/BiPushCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/BiPushCmd.java new file mode 100644 index 0000000000..c14e56b185 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/ByteCodeCommand.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..294add94b5 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/ByteCodeCommand.java @@ -0,0 +1,118 @@ +package miniJVM.cmd; + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantInfo; +import miniJVM.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.offset).append(": ").append(getReadableCodeText()); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode.toUpperCase()); + if(txt == null){ + return this.opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/cmd/CommandParser.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/CommandParser.java new file mode 100644 index 0000000000..1d45ffc35b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/CommandParser.java @@ -0,0 +1,147 @@ +package miniJVM.cmd; + + +import miniJVM.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 ci = new CommandIterator(codes); + List cmds = new ArrayList(); + while (ci.hasNext()){ + String command = ci.next2CharAsString(); + if(command.equalsIgnoreCase(new_object)){ + NewObjectCmd cmd = new NewObjectCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(invokespecial)){ + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(invokevirtual)){ + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(getfield)){ + GetFieldCmd cmd = new GetFieldCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(getstatic)){ + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(putfield)){ + PutFieldCmd cmd = new PutFieldCmd(clzFile, command); + cmd.setOprand1(ci.next2CharAsInt()); + cmd.setOprand2(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(ldc)){ + LdcCmd cmd = new LdcCmd(clzFile, command); + cmd.setOperand(ci.next2CharAsInt()); + cmds.add(cmd); + }else if(command.equalsIgnoreCase(bipush)){ + BiPushCmd cmd = new BiPushCmd(clzFile, command); + cmd.setOperand(ci.next2CharAsInt()); + cmds.add(cmd); + }else if (command.equalsIgnoreCase(dup) || + command.equalsIgnoreCase(aload_0) || + command.equalsIgnoreCase(aload_1) || + command.equalsIgnoreCase(aload_2) || + command.equalsIgnoreCase(iload_1) || + command.equalsIgnoreCase(iload_2) || + command.equalsIgnoreCase(iload_3) || + command.equalsIgnoreCase(fload_3) || + command.equalsIgnoreCase(voidreturn) || + command.equalsIgnoreCase(astore_1)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, command); + cmds.add(cmd); + }else{ + throw new RuntimeException("没有对指令=" + command + "进行处理"); + } + } + calculateOffset(cmds); + + ByteCodeCommand[] cmdArr = new ByteCodeCommand[cmds.size()]; + cmds.toArray(cmdArr); + return cmdArr; + } + + private static void calculateOffset(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/75939388/learning2017/src/main/java/miniJVM/cmd/GetFieldCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..67e734e5f1 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetStaticFieldCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..95ad38e806 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeSpecialCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..d4f401f26d --- /dev/null +++ b/group24/75939388/learning2017/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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeVirtualCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..37ebbf4cc2 --- /dev/null +++ b/group24/75939388/learning2017/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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/LdcCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/LdcCmd.java new file mode 100644 index 0000000000..c56b294f4d --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +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 = (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/75939388/learning2017/src/main/java/miniJVM/cmd/NewObjectCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..d2e28c5eea --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NewObjectCmd.java @@ -0,0 +1,20 @@ +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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NoOperandCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..e10bbabb66 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +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(); + } + + + public int getLength() { + return 1; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/cmd/OneOperandCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..6736c608b9 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +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; + + } + public int getLength(){ + return 2; + } + + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/cmd/PutFieldCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..066f37dd01 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +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/group24/75939388/learning2017/src/main/java/miniJVM/cmd/TwoOperandCmd.java b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..400fdb0350 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/TwoOperandCmd.java @@ -0,0 +1,64 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/ClassInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ClassInfo.java new file mode 100644 index 0000000000..735ae4eace --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/ConstantInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ConstantInfo.java new file mode 100644 index 0000000000..6ab8326c7f --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ConstantInfo.java @@ -0,0 +1,39 @@ +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 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 visitUTF8(UTF8Info info); + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/constant/ConstantPool.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ConstantPool.java new file mode 100644 index 0000000000..50042ec97d --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/FieldRefInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/FieldRefInfo.java new file mode 100644 index 0000000000..47603e4e13 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/MethodRefInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/MethodRefInfo.java new file mode 100644 index 0000000000..cd2f012b68 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/NameAndTypeInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..eddb11b6f5 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/NullConstantInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/NullConstantInfo.java new file mode 100644 index 0000000000..7df8b59156 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package miniJVM.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/constant/StringInfo.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/StringInfo.java new file mode 100644 index 0000000000..07be339e0a --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/StringInfo.java @@ -0,0 +1,32 @@ +package miniJVM.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/75939388/learning2017/src/main/java/miniJVM/constant/UTF8Info.java b/group24/75939388/learning2017/src/main/java/miniJVM/constant/UTF8Info.java new file mode 100644 index 0000000000..ff3518e492 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/constant/UTF8Info.java @@ -0,0 +1,37 @@ +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; + } + 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.visitUTF8(this); + + } + + + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/field/Field.java b/group24/75939388/learning2017/src/main/java/miniJVM/field/Field.java new file mode 100644 index 0000000000..cfaccf116c --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/field/Field.java @@ -0,0 +1,46 @@ +package miniJVM.field; + +import miniJVM.constant.ConstantPool; +import miniJVM.constant.UTF8Info; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private int attributeCount; + + private ConstantPool pool; + + public Field( int accessFlag, int nameIndex, int descriptorIndex, int attributeCount, ConstantPool pool) { + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.attributeCount = attributeCount; + 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 attrCount = iter.nextU2ToInt(); +// //System.out.println("field attribute count:"+ attribCount); +// +// Field f = new Field(accessFlag, nameIndex, descIndex,pool); +// +// if(attrCount > 0){ +// throw new RuntimeException("Field Attribute has not been implemented"); +// } +// +// return f; +// } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/loader/ByteCodeIterator.java b/group24/75939388/learning2017/src/main/java/miniJVM/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..7ab4e6cc97 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package miniJVM.loader; + +import miniJVM.util.Util; + +import java.util.Arrays; + +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/75939388/learning2017/src/main/java/miniJVM/loader/ClassFileLoader.java b/group24/75939388/learning2017/src/main/java/miniJVM/loader/ClassFileLoader.java new file mode 100644 index 0000000000..a96143321a --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/loader/ClassFileLoader.java @@ -0,0 +1,131 @@ +package miniJVM.loader; + + +import miniJVM.clz.ClassFile; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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 " + i + ", index -> " + index); + if (index == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.nextU2ToInt()); + pool.addConstantInfo(classInfo); + } else if (index == ConstantInfo.UTF8_INFO) { + UTF8Info utf8Info = new UTF8Info(pool); + int length = iter.nextU2ToInt(); + utf8Info.setLength(length); + utf8Info.setValue(new String(iter.getBytes(length), "utf8")); + pool.addConstantInfo(utf8Info); + } else if (index == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(methodRefInfo); + } else if (index == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameAndTypeInfo); + } else if (index == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(fieldRefInfo); + } else if (index == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(stringInfo); + } else if (index == 0) { + pool.addConstantInfo(null); + } else { + throw new Exception("没有针对tag=" + index + "的数据进行处理"); + } + } + clzFile.setConstPool(pool); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); +// System.out.println("interfaceCount:" + interfaceCount); + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFields(ByteCodeIterator iter) { + int fieldsCount = iter.nextU2ToInt(); + + for (int i = 0; i < fieldsCount; i++) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attributeCount = iter.nextU2ToInt(); + + Field field = new Field(accessFlag, nameIndex, descriptorIndex, attributeCount, pool); + clzFile.addField(field); + } + } + + private void parseMethods(ByteCodeIterator iter) { + int methodCount = iter.nextU2ToInt(); + + for (int i = 0; i < methodCount; i++) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); + int attributeCount = iter.nextU2ToInt();//=1 + while(attributeCount > 0){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + int exceptionTableLength = iter.nextU2ToInt(); + //异常先不处理 + String exceptionTable = iter.nextUxToHexString(exceptionTableLength); + + int subAttributeCount = iter.nextU2ToInt(); + while(subAttributeCount > 0){ + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + subAttributeCount--; + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + subAttributeCount--; + } + method.setCodeAttr(codeAttr); + attributeCount--; + } + clzFile.addMethod(method); + } + } + + private void parseStackMapTable(ByteCodeIterator iter){ + int stackMapCount = iter.nextU2ToInt(); + StackMapTable table = StackMapTable.parse(iter); + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/method/Method.java b/group24/75939388/learning2017/src/main/java/miniJVM/method/Method.java new file mode 100644 index 0000000000..d2e2ae2a27 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/method/Method.java @@ -0,0 +1,77 @@ +package miniJVM.method; + +import miniJVM.attr.CodeAttr; +import miniJVM.clz.ClassFile; +import miniJVM.cmd.ByteCodeCommand; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.UTF8Info; + +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){ +// return null; +// } + + public ByteCodeCommand[] getCmds() { + ByteCodeCommand[] cmds = this.getCodeAttr().getCmds(); + + return cmds; + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/print/ClassFilePrinter.java b/group24/75939388/learning2017/src/main/java/miniJVM/print/ClassFilePrinter.java new file mode 100644 index 0000000000..9d3d79bc85 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/print/ClassFilePrinter.java @@ -0,0 +1,42 @@ +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){ + String path = "resources/classes/miniJVM"; + 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/75939388/learning2017/src/main/java/miniJVM/print/ConstantPoolPrinter.java b/group24/75939388/learning2017/src/main/java/miniJVM/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..c776f49f01 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/print/ConstantPoolPrinter.java @@ -0,0 +1,114 @@ +package miniJVM.print; + + +import miniJVM.constant.*; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + System.out.println("Constant Pool:"); + int poolSize = pool.getSize(); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + public void visitClassInfo(ClassInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("Class "); + sb.append("#" + info.getUtf8Index()); + sb.append(" //" + info.getClassName()); + System.out.println(sb.toString()); + } + + public void visitFieldRef(FieldRefInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("Fieldref "); + sb.append("#" + info.getClassInfoIndex()); + sb.append("." + info.getNameAndTypeIndex()); + sb.append(" //" + info.getClassName()); + sb.append("." + info.getFieldName()); + sb.append(":" + info.getFieldType()); + System.out.println(sb.toString()); + } + + public void visitMethodRef(MethodRefInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("MethodRef "); + sb.append("#" + info.getClassInfoIndex()); + sb.append(".").append("#" + info.getNameAndTypeIndex()); + sb.append(" //" + info.getClassName()); + sb.append("." + info.getMethodName()); + sb.append(":" + info.getParamAndReturnType()); + System.out.println(sb.toString()); + } + + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("NameAndType "); + sb.append("#" + info.getIndex1()); + sb.append(":#" + info.getIndex2()); + sb.append(" //" + info.getName()); + sb.append(":" + info.getTypeInfo()); + System.out.println(sb.toString()); + } + + public void visitString(StringInfo info) { + StringBuilder sb = new StringBuilder(); + sb.append("String "); + sb.append("#" + info.getIndex()); + sb.append(" //" + info.toString()); + System.out.println(sb.toString()); + } + + public void visitUTF8(UTF8Info info) { + StringBuilder sb = new StringBuilder(); + sb.append("Utf8 "); + sb.append(info.getValue()); + System.out.println(sb.toString()); + } + }; + + for(int i = 1; i < poolSize; i++){ + System.out.print(i + "# = "); + ConstantInfo cnst = pool.getConstantInfo(i); + cnst.accept(visitor); +// if(cnst instanceof ClassInfo){ +// sb.append("Class "); +// sb.append("#" + ((ClassInfo) cnst).getUtf8Index()); +// sb.append(" //" + ((ClassInfo) cnst).getClassName()); +// }else if(cnst instanceof UTF8Info){ +// sb.append("Utf8 "); +// sb.append(((UTF8Info) cnst).getValue()); +// }else if(cnst instanceof MethodRefInfo){ +// sb.append("MethodRef "); +// sb.append("#" + ((MethodRefInfo) cnst).getClassInfoIndex()); +// sb.append(".").append("#" + ((MethodRefInfo) cnst).getNameAndTypeIndex()); +// sb.append(" //" + ((MethodRefInfo) cnst).getClassName()); +// sb.append("." + ((MethodRefInfo) cnst).getMethodName()); +// sb.append(":" + ((MethodRefInfo) cnst).getParamAndReturnType()); +// }else if(cnst instanceof NameAndTypeInfo){ +// sb.append("NameAndType "); +// sb.append("#" + ((NameAndTypeInfo) cnst).getIndex1()); +// sb.append(":#" + ((NameAndTypeInfo) cnst).getIndex2()); +// sb.append(" //" + ((NameAndTypeInfo) cnst).getName()); +// sb.append(":" + ((NameAndTypeInfo) cnst).getTypeInfo()); +// }else if(cnst instanceof FieldRefInfo){ +// sb.append("Fieldref "); +// sb.append("#" + ((FieldRefInfo) cnst).getClassInfoIndex()); +// sb.append("." + ((FieldRefInfo) cnst).getNameAndTypeIndex()); +// sb.append(" //" + ((FieldRefInfo) cnst).getClassName()); +// sb.append("." + ((FieldRefInfo) cnst).getFieldName()); +// sb.append(":" + ((FieldRefInfo) cnst).getFieldType()); +// }else if(cnst instanceof StringInfo){ +// sb.append("String "); +// sb.append("#" + ((StringInfo) cnst).getIndex()); +// sb.append(" //" + cnst.toString()); +// }else{ +// throw new RuntimeException(cnst.getType() + "not processed"); +// } + +// System.out.println(sb.toString()); + } + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/util/Util.java b/group24/75939388/learning2017/src/main/java/miniJVM/util/Util.java new file mode 100644 index 0000000000..ab4b651873 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/util/Util.java @@ -0,0 +1,24 @@ +package miniJVM.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" + s.toString()); - } - - @Test - public void testSize(){ - Stack s = getStack(); - - Assert.assertEquals(14, s.size()); + public void test1(){ + Assert.assertEquals("4,3,2,1,0", s.toString()); + Assert.assertEquals("13", s.pop()); + Assert.assertEquals(13, s.size()); + Assert.assertEquals("12", s.peek()); } @Test - public void testPeek(){ - Stack s = getStack(); + public void test2(){ +// Assert.assertEquals("0,1,2,3,4", StackUtil.reverse(s).toString()); +// Assert.assertEquals("0,1,3,4", StackUtil.remove(s, "2").toString()); +// Assert.assertEquals("[4, 3]", Arrays.toString(StackUtil.getTop(s, 2))); +// Assert.assertEquals(true, StackUtil.isValidPairs("([e{d}f])")); + Assert.assertEquals(false, StackUtil.isValidPairs("([b{x]y})")); - 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/data_structure/TokenParserTest.java b/group24/75939388/learning2017/src/test/java/data_structure/TokenParserTest.java new file mode 100644 index 0000000000..b8cde0cbed --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/TokenParserTest.java @@ -0,0 +1,42 @@ +package data_structure; + + +import basic.dataStructure.stack.expr.Token; +import basic.dataStructure.stack.expr.TokenParser; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +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/75939388/learning2017/src/test/java/miniJVM/ClassFileloaderTest.java b/group24/75939388/learning2017/src/test/java/miniJVM/ClassFileloaderTest.java new file mode 100644 index 0000000000..a1e230b9f0 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/miniJVM/ClassFileloaderTest.java @@ -0,0 +1,346 @@ +package miniJVM; + +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.*; +import miniJVM.field.Field; +import miniJVM.loader.ClassFileLoader; +import miniJVM.method.Method; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "miniJVM.EmployeeV1"; + + static String path1 = "resources/classes"; + static String path2 = "resources/classes"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); +// String className = "com.coderising.jvm.test.EmployeeV1"; +// String path = "resources/classes/EmployeeV1.class"; + String className = "miniJVM.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 = "miniJVM.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(FULL_QUALIFIED_CLASS_NAME); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1024, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); +// String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(FULL_QUALIFIED_CLASS_NAME); + 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/group24/75939388/learning2017/src/test/java/miniJVM/EmployeeV1.java b/group24/75939388/learning2017/src/test/java/miniJVM/EmployeeV1.java new file mode 100644 index 0000000000..e345de37ae --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/miniJVM/EmployeeV1.java @@ -0,0 +1,28 @@ +package miniJVM; + +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/75939388/learning2017/src/test/java/miniJVM/miniJVMTest.java b/group24/75939388/learning2017/src/test/java/miniJVM/miniJVMTest.java new file mode 100644 index 0000000000..9fb146de10 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/miniJVM/miniJVMTest.java @@ -0,0 +1,19 @@ +package miniJVM; + +import thread.download.ClassFileReader; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author : 温友朝 + * @date : 2017/4/18 + */ +public class miniJVMTest { + + @Test + public void readCafebabe(){ + Assert.assertEquals("cafebabe", ClassFileReader.readNextU4Bytes(0)); + } + + +}