diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java index 0ba1d9861c..2fdc34fc25 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/LinkedList.java @@ -318,7 +318,7 @@ public LinkedList intersection(LinkedList list){ LinkedList cList = new LinkedList(); - // TODO:为了方便起见,先各自复制并去重,虽然效率不高,以后有时间再优化 + // 为了方便起见,先各自复制并去重,虽然效率不高,以后有时间再优化 LinkedList aList = LinkedList.copy(this); LinkedList bList = LinkedList.copy(list); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..ff6f0f2699 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueue.java @@ -0,0 +1,72 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.ArrayDeque; + +/** + * 用数组实现循环队列,这也是一个队列,和普通队列有相同的外部特性,只是内部使用循环数组实现的罢了 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + protected int head = 0; + //队尾 + protected int rear = 0; // rear指向的位置不放值,也就是说即使满了,也有一个空位 + + public CircleQueue(int capacity) { + elementData = new Object[capacity+1]; // 实际的数组长度要比容量大1 + } + + public CircleQueue() { + } + + public boolean isEmpty() { + return head == rear; + } + + public int size() { + + return Math.floorMod(rear-head, elementData.length); + } + + /** + * 如果满了还往里面放,则抛IndexOutOfBoundsException异常 + */ + public void enQueue(E data) { + if (isFull()) throw new IndexOutOfBoundsException("循环队列已满"); + elementData[rear] = data; + rear = Math.floorMod(rear+1, elementData.length); + } + + /** + * 如果为空,则抛IndexOutOfBoundsException异常 + * @return + */ + public E deQueue() { + if (isEmpty()) throw new IndexOutOfBoundsException("循环队列为空"); + E result = (E) elementData[head]; + head = Math.floorMod(head+1, elementData.length); + return result; + } + + public boolean isFull() { + return size() == elementData.length-1; + } + + public static void main(String[] args) { + /** + Math.floorMod( 2, 3) = 2 + Math.floorMod(-2, 3) = 1 + Math.floorMod( 2, -3) = -1 + Math.floorMod(-2, -3) = -2 + */ + System.out.println(Math.floorMod(1-2, 5)); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..1b4c4d1887 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/CircleQueueTest.java @@ -0,0 +1,64 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class CircleQueueTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + CircleQueue queue = new CircleQueue(5); + Assert.assertTrue(queue.isEmpty()); + Assert.assertFalse(queue.isFull()); + + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + // System.out.println(queue.head); + // System.out.println(queue.rear); + queue.enQueue("d"); + queue.enQueue("e"); + + Assert.assertTrue(queue.isFull()); + Assert.assertFalse(queue.isEmpty()); + Assert.assertEquals(5, queue.size()); + + Assert.assertEquals("a", queue.deQueue()); + Assert.assertEquals("b", queue.deQueue()); + Assert.assertEquals("c", queue.deQueue()); + + Assert.assertFalse(queue.isFull()); + Assert.assertEquals(2, queue.size()); + + queue.enQueue("f"); + queue.enQueue("g"); + // System.out.println(queue.head); + // System.out.println(queue.rear); + Assert.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + // System.out.println(queue.head); + // System.out.println(queue.rear); + Assert.assertEquals("f", queue.deQueue()); + Assert.assertEquals("g", queue.deQueue()); + + Assert.assertEquals(0, queue.size()); + Assert.assertTrue(queue.isEmpty()); + Assert.assertFalse(queue.isFull()); + + // System.out.println(queue.head); + // System.out.println(queue.rear); + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..9f70edd16d --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/Josephus.java @@ -0,0 +1,37 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.LinkedList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + CircleQueue circleQueue = new CircleQueue<>(n); + List result = new LinkedList<>(); + for (int i=0; i { + private Node first; + private Node last; + private int size; + + + private static class Node { + private E item; + private Node next; + } + + + public Queue() { + first = null; + last = null; + size = 0; + } + + + public boolean isEmpty() { + return first == null; + } + + public int size() { + return size; + } + + + + public void enQueue(E data) { + Node oldlast = last; + last = new Node(); + last.item = data; + last.next = null; + if (isEmpty()) { + first = last; + } + else{ + oldlast.next = last; + } + size++; + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue underflow"); + } + E item = first.item; + first = first.next; + size--; + if (isEmpty()) { + last = null; + } + return item; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c936547f62 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * @author liuxin + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + private void move(Stack s1, Stack s2) { + while (!s1.empty()) { + s2.push(s1.pop()); + } + } + + public int size() { + return stack1.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + move(stack1, stack2); + E result = stack2.pop(); + move(stack2, stack1); + return result; + } + + } + diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..30c3268c5a --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,52 @@ +package com.github.miniyk2012.coding2017.basic.queue; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +/** +* QueueWithTwoStacks Tester. +* +* @author +* @since
May 3, 2017
+* @version 1.0 +*/ +public class QueueWithTwoStacksTest { + QueueWithTwoStacks queue; + + @Before + public void before() throws Exception { + queue = new QueueWithTwoStacks<>(); + } + + @After + public void after() throws Exception { + } + + @Test + public void testFunction() { + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + queue.enQueue("d"); + Assert.assertEquals(4, queue.size()); + Assert.assertFalse(queue.isEmpty()); + + Assert.assertEquals("a", queue.deQueue()); + Assert.assertEquals("b", queue.deQueue()); + Assert.assertEquals("c", queue.deQueue()); + Assert.assertEquals(1, queue.size()); + Assert.assertFalse(queue.isEmpty()); + + queue.enQueue("e"); + Assert.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + Assert.assertTrue(queue.isEmpty()); + Assert.assertEquals(0, queue.size()); + + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java new file mode 100644 index 0000000000..e69042a583 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/ExprUtil.java @@ -0,0 +1,53 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; + +/** + * Created by thomas_young on 30/4/2017. + */ +public class ExprUtil { + + /** + * 求值 + * @param operand1 操作数1 + * @param operator 操作符 + * @param operand2 操作数2 + * @return Token表示的值 + */ + public static Token evalute(Token operand1, Token operator, Token operand2) { + float resultValue; + switch (operator.value) { + case "+": { + resultValue = operand1.getFloatValue() + operand2.getFloatValue(); + break; + } + case "-": { + resultValue = operand1.getFloatValue() - operand2.getFloatValue(); + break; + } + case "*": { + resultValue = operand1.getFloatValue() * operand2.getFloatValue(); + break; + } + case "/": { + resultValue = operand1.getFloatValue() / operand2.getFloatValue(); + break; + } + default: throw new RuntimeException("不支持的运算符:" + operator.value); + } + return new Token(Token.NUMBER, String.valueOf(resultValue)); + } + + public static String tokens2String(List tokens) { + StringBuffer buffer = new StringBuffer(); + int i = 0; + for (Token token: tokens) { + if (i != tokens.size()-1) + buffer.append(token.toString()+" "); + else + buffer.append(token.toString()); + i++; + } + return buffer.toString(); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java index 92727ce984..69d1b41a0e 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java @@ -1,5 +1,6 @@ package com.github.miniyk2012.coding2017.basic.stack.expr; +import java.util.EmptyStackException; import java.util.LinkedList; import java.util.List; import java.util.Stack; @@ -61,11 +62,16 @@ public float evaluate() { operatorStack.push(t); } else { Token preT = operatorStack.peek(); - if ((preT.value).priority >= ((Operator)t.value).priority) { + while (preT.value.priority >= ((Operator)t.value).priority) { Token number2 = numberStack.pop(); Token number1 = numberStack.pop(); operatorStack.pop(); numberStack.push(evaluate(preT, number1, number2)); + try { + preT = operatorStack.peek(); + } catch (EmptyStackException e) { + break; + } } operatorStack.push(t); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java index 706aaea86e..5906221e79 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java @@ -19,6 +19,10 @@ public void tearDown() throws Exception { @Test public void testEvaluate() { //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2"); + Assert.assertEquals(2.0, expr.evaluate(), 0.001f); + } { InfixExpr expr = new InfixExpr("2+3"); Assert.assertEquals(5.0, expr.evaluate(), 0.001f); @@ -46,7 +50,14 @@ public void testEvaluate() { InfixExpr expr = new InfixExpr("10-30+50"); Assert.assertEquals(30, expr.evaluate(), 0.001f); } - + { + InfixExpr expr = new InfixExpr("10-30+50-20/10/2*4"); + Assert.assertEquals(26, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-30+50-20/1+10"); + Assert.assertEquals(20, expr.evaluate(), 0.001f); + } } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..d99971e5b6 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,53 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.EmptyStackException; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +/** + * Shunting-yard algorithm + * https://en.wikipedia.org/wiki/Shunting-yard_algorithm + 初始化一个运算符栈和一个输出队列 + 不断读取token + 如果token是一个数 + 将其放入输出队列 + 如果token是一个运算符o1 + while栈顶部有运算符o2: + 如果o1的优先级小于等于o2,把o2取出放到输出队列 + 最后push(o1) + 将栈中的操作符逐个出栈放到输出队列 + */ +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack operatorStack = new Stack<>(); + List outputTokens = new LinkedList<>(); + for (Token token: tokens) { + if (token.isNumber()) { + outputTokens.add(token); + } else { + while (true) { + try { + Token o2 = operatorStack.peek(); + if (!token.hasHigherPriority(o2)) { + operatorStack.pop(); + outputTokens.add(o2); + } else { + break; + } + } catch (EmptyStackException e) { + break; + } + } + operatorStack.push(token); + } + } + while (!operatorStack.isEmpty()) { + outputTokens.add(operatorStack.pop()); + } + return outputTokens; + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..b363e58e35 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,67 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +import java.util.List; + +/** +* InfixToPostfix Tester. +* +* @author +* @since
Apr 30, 2017
+* @version 1.0 +*/ +public class InfixToPostfixTest { + + @Before + public void before() throws Exception { + } + + @After + public void after() throws Exception { + } + + /** + * + * Method: convert(String expr) + * + */ + @Test + public void testConvert() throws Exception { + { + String infixExpr = "3+4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("3 4 +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 * 3 + 4 * 6"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 * 4 6 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 * 3 / 4 * 6"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 * 4 / 6 *", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1 + 3 * 4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 4 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "3+2*3+4*5"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("3 2 3 * + 4 5 * +", ExprUtil.tokens2String(tokens)); + } + { + String infixExpr = "1-3+5-2/1/2*4"; + List tokens = InfixToPostfix.convert(infixExpr); + Assert.assertEquals("1 3 - 5 + 2 1 / 2 / 4 * -", ExprUtil.tokens2String(tokens)); + } + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..6475450e4c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,51 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + + +/** + https://en.wikipedia.org/wiki/Reverse_Polish_notation + + While there are input tokens left + Read the next token from input. + If the token is a value + Push it onto the stack. + Otherwise, the token is an operator (operator here includes both operators and functions). + It is already known that the operator takes n arguments. + If there are fewer than n values on the stack + (Error) The user has not input sufficient values in the expression. + Else, Pop the top n values from the stack. + Evaluate the operator, with the values as arguments. + Push the returned results, if any, back onto the stack. + If there is only one value in the stack + That value is the result of the calculation. + Otherwise, there are more values in the stack + (Error) The user input has too many values. + */ +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack operandStack = new Stack<>(); + for (Token token: tokens) { + if (token.isNumber()) { + operandStack.push(token); + } else { + Token operand1 = operandStack.pop(); + Token operand2 = operandStack.pop(); + Token result = ExprUtil.evalute(operand2, token, operand1); + operandStack.push(result); + } + } + return operandStack.pop().getFloatValue(); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..24aa8f44f5 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + PostfixExpr expr = new PostfixExpr("6 5 2 3 + 8 * + 3 + *"); + Assert.assertEquals(288, expr.evaluate(),0.0f); + } + { + //9+(3-1)*3+10/2 + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + Assert.assertEquals(20, expr.evaluate(),0.0f); + } + + { + //10-2*3+50 + PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); + Assert.assertEquals(54, expr.evaluate(),0.0f); + } + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..20f0a15e9c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,51 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +/** + https://en.wikipedia.org/wiki/Polish_notation + Scan the given prefix expression from right to left + for each symbol + { + if operand then + push onto stack + if operator then + { + operand1=pop stack + operand2=pop stack + compute operand1 operator operand2 + push result onto stack + } + } + return top of stack as result + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Collections.reverse(tokens); + Stack operandStack = new Stack<>(); + for (Token token: tokens) { + if (token.isNumber()) { + operandStack.push(token); + } else { + Token operand1 = operandStack.pop(); + Token operand2 = operandStack.pop(); + Token result = ExprUtil.evalute(operand1, token, operand2); + operandStack.push(result); + } + } + + return operandStack.pop().getFloatValue(); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..4a0a0955b3 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + // 2*3+4*5 + PrefixExpr expr = new PrefixExpr("+ * 2 3* 4 5"); + Assert.assertEquals(26, expr.evaluate(),0.001f); + } + { + // 4*2 + 6+9*2/3 -8 + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + Assert.assertEquals(12, expr.evaluate(),0.001f); + } + { + //(3+4)*5-6 + PrefixExpr expr = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29, expr.evaluate(),0.001f); + } + { + //1+((2+3)*4)-5 + PrefixExpr expr = new PrefixExpr("- + 1 * + 2 3 4 5"); + Assert.assertEquals(16, expr.evaluate(),0.001f); + } + + + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java new file mode 100644 index 0000000000..afaa4a8a41 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/Token.java @@ -0,0 +1,54 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Token { + public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + private static final Map priorities = new HashMap<>(); + static { + priorities.put("+", 1); + priorities.put("-", 1); + priorities.put("*", 2); + priorities.put("/", 2); + } + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + public Token(int type, String value){ + this.type = type; + this.value = value; + } + + public boolean isNumber() { + return type == NUMBER; + } + + public boolean isOperator() { + return type == OPERATOR; + } + + public float getFloatValue() { + return Float.parseFloat(value); + } + + public int getIntValue() { + return Integer.parseInt(value); + } + public String toString(){ + return value; + } + + public boolean hasHigherPriority(Token t){ + if(!this.isOperator() && !t.isOperator()){ + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + + + +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..aa4e0560cf --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + + public List parse(String expr) { + List tokens = new ArrayList<>(); + + int i = 0; + + while (i < expr.length()) { + + char c = expr.charAt(i); + + if (isOperator(c)) { + + Token t = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(t); + i++; + + } else if (Character.isDigit(c)) { + + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token t = new Token(Token.NUMBER, value); + tokens.add(t); + i = nextOperatorIndex; + + } else{ + System.out.println("char :["+c+"] is not number or operator,ignore"); + i++; + } + + } + return tokens; + } + + private int indexOfNextOperator(int i, String expr) { + + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + + } + + private boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..92b54d0bb7 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.github.miniyk2012.coding2017.basic.stack.expr; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class 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"); + float delta = 0.0001f; + Assert.assertEquals(300, tokens.get(0).getFloatValue(), delta); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getFloatValue(), delta); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getFloatValue(), delta); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getFloatValue(), delta); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getFloatValue(), delta); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getFloatValue(), delta); + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java index 41bc6ad344..bedf53dbc9 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/array/ArrayUtil.java @@ -119,7 +119,7 @@ public int[] fibonacci(int max){ * @return */ public int[] getPrimes(int max){ - // TODO 使用筛法,写的不好,有待改善 + // TODO 使用筛法,写的不好,有待改善,见《敏捷开发》一书,我有空就重构 if (max <= 2) return new int[0]; List list = new ArrayList<>(); int i; diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..661e65bb2b --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCEPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVariableTable"; + public static final String STACK_MAP_TABLE = "StackMapTable"; + int attrNameIndex; + int attrLen ; + public AttributeInfo(int attrNameIndex, int attrLen) { + + this.attrNameIndex = attrNameIndex; + this.attrLen = attrLen; + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..640250343f --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,104 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.attr; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.ByteCodeCommand; +import com.github.miniyk2012.coding2017.coderising.jvm.cmd.CommandParser; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + public String getCode() { + return code; + } + + private ByteCodeCommand[] cmds ; + public ByteCodeCommand[] getCmds() { + return cmds; + } + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, + int attrLen, + int maxStack, + int maxLocals, + int codeLen, + String code, + ByteCodeCommand[] cmds) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + int attributeNameIndex = iter.nextU2toInt(); + int attributeLength = iter.nextU4toInt(); + int maxStack = iter.nextU2toInt(); + int maxLocals = iter.nextU2toInt(); + int codeLength = iter.nextU4toInt(); + + String code = iter.nextUxToHexString(codeLength); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code, cmds); + + int exceptionTableLen = iter.nextU2toInt(); + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + } + + int attributesCount = iter.nextU2toInt(); + for (int i=0; i items = new ArrayList<>(); + + private static class LineNumberItem{ + int startPC; + int lineNum; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLineNum() { + return lineNum; + } + public void setLineNum(int lineNum) { + this.lineNum = lineNum; + } + } + public void addLineNumberItem(LineNumberItem item){ + this.items.add(item); + } + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + public static LineNumberTable parse_V2(ByteCodeIterator iter){ + + int index = iter.nextU2toInt(); + int len = iter.nextU4toInt(); + + LineNumberTable table = new LineNumberTable(index,len); + + int itemLen = iter.nextU2toInt(); + + for(int i=1; i<=itemLen; i++){ + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.nextU2toInt()); + item.setLineNum(iter.nextU2toInt()); + table.addLineNumberItem(item); + } + return table; + } + + public static LineNumberTable parse(ByteCodeIterator iter){ + int nameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU4toInt(); + int tableLen = iter.nextU2toInt(); + LineNumberTable table = new LineNumberTable(nameIndex, attrLen); + + for (int i=0; i items = new ArrayList<>(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + int nameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU4toInt(); + LocalVariableTable table = new LocalVariableTable(nameIndex, attrLen); + int tableLen = iter.nextU2toInt(); + + for(int i=0; i fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -24,8 +30,6 @@ public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - public ConstantPool getConstantPool() { return pool; } @@ -43,31 +47,54 @@ public void setMajorVersion(int majorVersion) { } public void setConstPool(ConstantPool pool) { this.pool = pool; - + } + public void addField(Field f){ + this.fields.add(f); + } + public List getFields(){ + return this.fields; + } + public void addMethod(Method m){ + this.methods.add(m); + } + public List getMethods() { + return methods; } public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - public void print(){ - if(this.accessFlag.isPublicClass()){ System.out.println("Access flag : public "); } System.out.println("Class Name:"+ getClassName()); - System.out.println("Super Class Name:"+ getSuperClassName()); } - private String getClassName(){ + public String getClassName(){ int thisClassIndex = this.clzIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } - private String getSuperClassName(){ + public String getSuperClassName(){ ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } + + public Method getMethod(String methodName, String paramAndReturnType){ + for (Method method: methods) { + String mName = method.getMethodName(); + String desc = method.getDescriptor(); + if (mName.equals(methodName) && desc.equals(paramAndReturnType)) { + return method; + } + } + return null; + } + + public Method getMainMethod(){ + return getMethod("main", "([Ljava/lang/String;)V"); + } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/BiPushCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..81fc933920 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..46d0966ea9 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,123 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantInfo; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + + +public abstract class ByteCodeCommand { + + String opCode; // 该指令的助记符 + ClassFile clzFile; + private int offset; // 该命令在某方法指令中的偏移量 + + private static Map codeMap = new HashMap(); // 二级制码与助记符的对应关系 + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + protected ConstantInfo getConstantInfo(int index){ + return getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); // 以后goto语句要用到 + + @Override + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + throw new RuntimeException("codeMap don't contain: " + opCode); + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..a21a9f66a3 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,147 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; + +import java.util.LinkedList; +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 cIter = new CommandIterator(codes); + List cmds = new LinkedList<>(); + // 将字符串解析为ByteCodeCommand[] + while (cIter.hasNext()) { // todo 重构,1.不应该用这么多的if语句 2.大量重复代码 + String opCode = cIter.next2CharAsString().toUpperCase(); + if (opCode.equalsIgnoreCase(getfield)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(getstatic)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(invokespecial)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(invokevirtual)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(ldc)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(new_object)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(putfield)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(cIter.next2CharAsInt()); + cmd.setOprand2(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(bipush)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(cIter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equalsIgnoreCase(aload_0) + || opCode.equalsIgnoreCase(aload_1) + || opCode.equalsIgnoreCase(aload_2) + || opCode.equalsIgnoreCase(astore_1) + || opCode.equalsIgnoreCase(iload_1) + || opCode.equalsIgnoreCase(iload_2) + || opCode.equalsIgnoreCase(voidreturn) + || opCode.equalsIgnoreCase(dup) + ) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("not implement cmd: " + opCode); + } + + } + calcuateOffset(cmds); + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; + } + + private static void calcuateOffset(List cmds) { + + int offset = 0; + for (ByteCodeCommand cmd : cmds) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + + } + + private static class CommandIterator { + String codes = null; + int pos = 0; + + CommandIterator(String codes) { + this.codes = codes; + } + + public boolean hasNext() { + return pos < this.codes.length(); + } + + public String next2CharAsString() { + String result = codes.substring(pos, pos + 2); + pos += 2; + return result; + } + + public int next2CharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..f996abe54c --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..5627e5efb0 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..0ff685b960 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..f9688b128b --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..1aef5af580 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantInfo; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = pool.getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..6bcac6b662 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..d63e47ae17 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + + public int getLength(){ + return 1; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..00e7b09a67 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + private int operand; + + public OneOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + public int getOperand() { + + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + + } + public int getLength(){ + return 2; + } + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..46a878940f --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,18 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..9cb8173567 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,63 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.cmd; + + +import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; + +public abstract class TwoOperandCmd extends ByteCodeCommand{ + + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + public int getOprand2() { + return oprand2; + } + + public TwoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + public int getIndex(){ + int oprand1 = this.getOprand1(); + int oprand2 = this.getOprand2(); + int index = oprand1 << 8 | oprand2; + return index; + } + + protected String getOperandAsClassInfo(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + + protected String getOperandAsField(ConstantPool pool){ + int index = getIndex(); + + String codeTxt = getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + public int getLength(){ + return 3; + } +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java index 98c5ced1a9..b69e5aebc6 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/constant/FieldRefInfo.java @@ -34,9 +34,6 @@ public String toString(){ public String getClassName(){ ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); - - // UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); - // return utf8Info.getValue(); return classInfo.getClassName(); } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..7507e0a2af --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/field/Field.java @@ -0,0 +1,49 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.field; + + +import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool; +import com.github.miniyk2012.coding2017.coderising.jvm.constant.UTF8Info; +import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private ConstantPool pool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + // String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + String name = pool.getUTF8String(nameIndex); + + //String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + String desc = pool.getUTF8String(descriptorIndex); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2toInt(); + int nameIndex = iter.nextU2toInt(); + int descIndex = iter.nextU2toInt(); + int attribCount = iter.nextU2toInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex, pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java index 73eb2fc1ff..1cd3b700aa 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ByteCodeIterator.java @@ -11,7 +11,7 @@ public class ByteCodeIterator { private int point = 0; public ByteCodeIterator(byte[] codes) { - this.codes = codes; + this.codes = codes.clone(); } public int nextU1toInt() { @@ -24,6 +24,10 @@ public int nextU2toInt() { return Util.byteToInt(u2); } + public int nextU4toInt() { + return Util.byteToInt(new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] }); + } + /** * 读取n个字节,并编码成UTF-8输出,point自动增加 * @param n @@ -31,6 +35,10 @@ public int nextU2toInt() { */ public String readUtf8(int n) { + if (point + n >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + byte[] info = Arrays.copyOfRange(codes, point, point+n); String utf8; try { @@ -63,6 +71,20 @@ public void seek(int n) { point = n; } + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[point++], codes[point++], codes[point++], codes[point++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[point++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + public static void main(String[] args) throws UnsupportedEncodingException { byte[] codes = {0x00, 0x34, 0x00}; ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes); diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java index 7b84a15899..1e7ad606d9 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/loader/ClassFileParser.java @@ -1,9 +1,12 @@ package com.github.miniyk2012.coding2017.coderising.jvm.loader; + import com.github.miniyk2012.coding2017.coderising.jvm.clz.AccessFlag; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile; import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex; import com.github.miniyk2012.coding2017.coderising.jvm.constant.*; +import com.github.miniyk2012.coding2017.coderising.jvm.field.Field; +import com.github.miniyk2012.coding2017.coderising.jvm.method.Method; public class ClassFileParser { @@ -12,7 +15,12 @@ public ClassFile parse(byte[] codes) { ClassFile clzFile = new ClassFile(); ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes); - byteCodeIterator.skip(4); // skip magic + // byteCodeIterator.skip(4); // skip magic number + String magicNumber = byteCodeIterator.nextU4ToHexString(); + + if (!"cafebabe".equals(magicNumber)) { + return null; + } int minorVersion = byteCodeIterator.nextU2toInt(); int majorVersion = byteCodeIterator.nextU2toInt(); ConstantPool constantPool = parseConstantPool(byteCodeIterator); @@ -24,6 +32,10 @@ public ClassFile parse(byte[] codes) { clzFile.setConstPool(constantPool); clzFile.setAccessFlag(accessFlag); clzFile.setClassIndex(classIndex); + + parseInterfaces(byteCodeIterator); + parseFileds(clzFile, byteCodeIterator); + parseMethods(clzFile, byteCodeIterator); return clzFile; } @@ -55,6 +67,33 @@ protected ConstantPool parseConstantPool(ByteCodeIterator iter) { return constantPool; } + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2toInt(); + + // System.out.println("interfaceCount:" + interfaceCount); + for (int i=0; i fields = clzFile.getFields(); + Assert.assertEquals(2, fields.size()); + { + Field f = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + private void assertMethodEquals(ConstantPool pool, Method m , String expectedName, String expectedDesc, String expectedCode){ + String methodName = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + String code = m.getCodeAttr().getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } + + + /** + * 下面是第四次作业Cmd的测试用例 + */ + + @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); + } + + /** + * 编写代码时做的一些测试用例 + */ + @Test + @Ignore + public void otherThing() { + { // Method的若干方法 + Method mainMethod = this.clzFile.getMainMethod(); + Assert.assertEquals("main", mainMethod.getMethodName()); + Assert.assertEquals("([Ljava/lang/String;)V", mainMethod.getDescriptor()); + System.out.println(mainMethod); + } + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + System.out.println(sayHelloMethod); + } + { + Method setNameMethod = this.clzFile.getMethod("setName", "(Ljava/lang/String;)V"); + System.out.println(setNameMethod); + } + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + System.out.println(initMethod); + } + } }